I have an array with numbers. I would like to put the numbers in order and create new array with duplicats in the same array(array in array). Can someone please help me step by step. I would really like to understand
let arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
// I want to create this [[1,1,1,1],[2,2,2], 4,5,10,[20,20], 391, 392,591]
const sortArray = arr.sort(function(a, b) {
return a - b;
});
You can extract unique values using Set, then sort them (because sorting an array of arrays is more complex), then use array.reduce to acquire all the items in the original array and push either the single value if unique, otherwise the array of values (not sure why you need that, but still..)
Further documentation reference:
What is Set?
Array.reduce
Working code below:
let arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
// I want to create this [[1,1,1,1],[2,2,2], 4,5,10,[20,20], 391, 392,591]
console.log([...new Set(arr)].sort((a,b) => a - b).reduce((accumulator, next) => {
const filtered = arr.filter(i => i === next);
return accumulator.push(filtered.length === 1 ? filtered[0] : filtered), accumulator
}, []));
You could sort the array and have a look to the last two items and the actual item.
[ 1, 1, 1, 1, 2, 2, 2, 4, 5, 10, 20, 20, 391, 392, 591] array
a b c variables
^ actual item
Then check if the last item b and the actual item c is unequal and return a new array with the the old items and the actual item.
If the item before the last item a and the actual item is unequal, it should be an array for the last item in the result set and the actual item.
Otherwise push the actual item to the nested last array of the result set.
var array = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20],
result = array
.sort((a, b) => a - b)
.reduce((r, c, i, { [i - 2]: a, [i - 1]: b }) => {
if (b !== c) return [...r, c];
if (a !== c) return r.pop(), [...r, [b, c]];
r[r.length - 1].push(c);
return r;
}, []);
console.log(result);
Although there are other approaches, whenever I need to parse unique values from an array in this way, I will create an object with the object's properties representing the groupings of array values
{ 1: [1, 1, 1], 2: [2 , 2, 2], 4: [4], 5: [5] ...}
Then you can use a native object method to get all keys or values from the object if you need to (or if your end goal is different, you can use the object however it is needed)
Object.keys(obj)
// or
Object.values(obj)
For your case, it would look like
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const obj = arr.reduce((accum, val) => {
accum[val] = accum[val] || [];
accum[val].push(val);
return accum;
}, {});
const finalArr = Object.values(obj).map(val => val.length > 1 ? val : val[0]);
console.log(finalArr);
You can count the occurrences and then use that object to create your final array.
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const count = arr.reduce((acc, val) => {
acc[val] = acc[val] + 1 || 1;
return acc;
}, {});
const result = Object
.keys(count)
.sort((a, b) => a - b)
.map((key) => count[key] === 1 ? +key : Array.from({ length: count[key] }).fill(+key));
console.log(result);
You can do this thing in ways. But if you want to achieve in best way, you must avoid n square loops.
So can create a dictionary of count of values. And loop over the keys of the object in sorted order.
Using Array.reduce to create object of count of array elemnts. and Array.fill to fil an array with same values.
//Given Array
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
//Dictionary with count of each values in array
const arrCountObj = arr.reduce((acc, el) => {
if (acc[el]) {
acc[el] += 1
} else {
acc[el] = 1
}
return acc
}, {})
console.log(arrCountObj)
//Looping over sorted dictionary keys to create array based on condition
var out = Object.keys(arrCountObj).sort((a, b) => a - b).map(x => arrCountObj[x] > 1 ? new Array(arrCountObj[x]).fill(+x) : arrCountObj[x])
console.log(out)
Time Complexity: O(nlogn)
You could:
1) iterate through the array an build a frequency map of the the numbers
2) grab and sort the frequency map key in ascending order
3) build a new array from the information in the frequency map
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const obj = arr.reduce((acc, c) => {
return acc[c] = (acc[c] || 0) + 1, acc;
}, {});
// {"1":4,"2":3,"4":1,"5":1,"10":1,"20":2,"391":1,"392":1,"591":1}
const keys = Object.keys(obj).sort((a, b) => a - b).map(Number);
// [1,2,4,5,10,20,391,392,591]
const out = keys.map((key) => {
return obj[key] > 1 ? Array(obj[key]).fill(key) : key;
});
// [[1,1,1,1],[2,2,2],4,5,10,[20,20],391,392,591]
console.log(JSON.stringify(out));
You can use reduce and then Array.fill. Here the reduce will create an object like this
{
"1": 4,
"2": 3,
"4": 1,
"5": 1,
"10": 1,
"20": 2,
"391": 1,
"392": 1,
"591": 1
}
which mean there are 4 1s, 3 2s and so on. Then you can use array fill after iterating this object. The array fill syntax is arr.fill(value[, start[, end]])
So in our case we will case new Array(k[keys]).fill(+keys, 0, k[keys]) is creating a new array of length 4,3 so on except for 1 and from 0th index it is filling with the key
let arr = [1, 2, 4, 591, 392, 391,1, 2, 5, 10, 2, 1, 1, 1, 20, 20];
let k = arr.reduce(function(acc, curr) {
if (curr in acc) {
acc[curr] += 1;
} else {
acc[curr] = 1
}
return acc;
}, {});
let grouped = [];
for (let keys in k) {
if (k[keys] !== 1) {
grouped.push(new Array(k[keys]).fill(+keys, 0))
} else {
grouped.push(+keys)
}
}
console.log(grouped)
Related
let arrr = [7, 9, 30, 40, 50, 8, 1, 2, 3, 40, 90,2, 88,1];
output=[0, 1, 2, 3, 4, 5, 6, 7, 8 ,10, 12 ]
I saved this code at javascript playground here.
Question: I am trying to get all the index of unique elements in array. I have tried the code below to get the unqiue array but i do not know how to extract its index to give the expected output as above.
let ar = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 2, 1];
let unique = ar.filter((value, index) => {
return ar.indexOf(value) == index;
});
console.log(unique);
.indexOf() will always return the index of the first match. If we combine that with a Set we get the expected output:
let input = [7, 9, 30, 40, 50, 8, 1, 2, 3, 40, 90, 2, 88, 1];
const indices = input.map(el => input.indexOf(el));
const output = new Set(indices);
const output_as_array = [...output]; // if you need an actual array
console.log(output_as_array);
Use a set to record numbers that have already been seen, and add the index to an array if it has not been see.
function uniqueIndices(arr) {
const seen = new Set();
const indices = [];
for (const [i, n] of arr.entries()) {
if (!seen.has(n)) {
seen.add(n);
indices.push(i);
}
}
return indices;
}
This also works well as a generator:
function *uniqueIndices(arr) {
const seen = new Set();
for (const [i, n] of arr.entries()) {
if (!seen.has(n)) {
seen.add(n);
yield i;
}
}
}
console.log([...uniqueIndices([7, 9, 30, 40, 50, 8, 1, 2, 3, 40, 90,2, 88,1])])
A simple function which iterates the list just once, storing the value and index in a Map, simply testing whether it's already there before adding a new one:
const uniqueIndices = (xs) =>
[...xs .reduce ((found, x, i) => found .has (x) ? found : found .set (x, i), new Map()) .values ()]
const arr = [7, 9, 30, 40, 50, 8, 1, 2, 3, 40, 90, 2, 88, 1]
console .log (uniqueIndices (arr))
.as-console-wrapper {max-height: 100% !important; top: 0}
Get all the unique values
Map over the uniques to use indexOf on the original array to get the indexes of the uniques
let arrr = [7, 9, 30, 40, 50, 8, 1, 2, 3, 40, 90,2, 88,1];
let unique = arrr.filter((v, i, a) => a.indexOf(v) === i);
let uniquesIndexes = unique.map(u => arrr.indexOf(u));
console.log(uniquesIndexes)
Output:
[
0,
1,
2,
3,
4,
5,
6,
7,
8,
10,
12
]
Is there any way to only triplicate certain elements in an array? I want to triplicate the "3" in the array only.
For instance:
const deck = [1, 3, 9, 3, 7];
should become [1, 3, 3, 3, 9, 3, 3, 3, 7]
I have tried the method below, deck is the random array:
var i;
for (let i=0;i<deck.length;i++){
if (deck[i]==3){
return deck.flatMap(x=>[x,x,x]);
}else return deck[i];
}
}
You could write a function that uses flatMap() to map over the array and triplicate the specific values.
const deck = [1, 3, 9, 3, 7];
const triplicate = (number, arr) => {
return arr.flatMap(x => x === number ? [x, x, x]: x);
}
console.log(triplicate(3, deck));
Using Array#flatMap:
const triplicate = (arr = [], number) =>
arr.flatMap(n => n === number ? [n, n, n] : n);
console.log( triplicate([1, 3, 9, 3, 7], 3) );
I have an array and what I want to do with this if to check if all the elements has the same magnitude for example:
array [40, 20, 30, 10] has 10 as magnitude so output should be true
array [1, 2, 3, 1, 2, 3] has 1 as magnitude so output should be true
array [2, 6, 12, 20] has more than one magnitude so output should be false
The could should be work with integers and floats, incluiding negative numbers.
What I tried is to use some code from here but seems that this only works for consecutive numbers and if there are repeated x times. So I wonder if this code can be addapted to fix my problem or if there is another way to solve it.
Code:
function consecutive(array) {
var i = 2, d;
while (i < array.length) {
d = array[i - 1] - array[i - 2];
if (Math.abs(d) === 1 && d === array[i] - array[i - 1]) {
return false;
}
i++;
}
return true;
}
var array = [3, 2, 1, 2, 3, 4, 3]; // Return true
// var array = [194, 54, 23, 7, 3, 6, 8 ] //Example 2 Return false
console.log(consecutive(array));
I guess this should do the trick...
// array [40, 20, 30, 10] has 10 as magnitude so output should be true
// array [1, 2, 3, 1, 2, 3] has 1 as magnitude so output should be true
// array [2, 6, 12, 20] has more than one magnitude so output should be false
const arr1 = [40, 20, 30, 10];
const arr2 = [1, 2, 3, 1, 2, 3];
const arr3 = [2, 6, 12, 20];
const magnitude = items => {
const unique = [...new Set(items)];
const sorted = unique.sort((a,b) => a-b);
const mags = [];
sorted.forEach((item, idx) => {
if (idx + 1 >= sorted.length) return null;
const next = sorted[idx + 1];
mags.push(item - next);
});
return [...new Set(mags)].length <= 1;
};
console.log('arr1', magnitude(arr1));
console.log('arr2', magnitude(arr2));
console.log('arr3', magnitude(arr3));
You can try like below
const arr1 = [40.10, 20.10, 30.10, 10.10, 50.20];
const arr2 = [40.10, 20.10, 30.10, 10.10, 50.10];
const arr3 = [40, 20, 30, 10, 50];
const hasSameMagnitue = (values: number[]): boolean => {
const sortByOrder = values.sort();
const diff = sortByOrder.slice(0, -1).map((el, index) => (sortByOrder[index + 1] - el).toFixed(2));
const result = diff.every((el) => el === diff[0]);
return result;
}
console.log('hasSameMagnitue', hasSameMagnitue(arr1)); // false
console.log('hasSameMagnitue', hasSameMagnitue(arr2)); // true
console.log('hasSameMagnitue', hasSameMagnitue(arr3)); // true
I would like to interleave two arrays, BUT only return pairs when a certain condition is met. As an example:
first_array = [1, 2, 3, 4, 5, 6, 7, 8];
second_array = [, , , , 1, , 0, 1];
I need to return ONLY pairs where array-2 is non-null, in other words, the output I need is:
interleaved = [5, 1, 7, 0, 8, 1];
I have an interleave function that works:
function send_values() {
let interleaved = [];
for (let i = 0; i < first_array.length; i++) {
interleaved.push(first_array[i], second_array[i]);
}
}
...but the output is, obviously:
interleaved = [1, , 2, , 3, , 4, , 5, 1, 6, , 7, 0, 8, 1];
...which is not what I need. Suggestions?
You could iterate the sparse array and take only the values with the values at the same index from array one.
var array1 = [1, 2, 3, 4, 5, 6, 7, 8],
array2 = [, , , , 1, , 0, 1],
result = array2.reduce((r, v, i) => r.concat(array1[i], v), []);
console.log(result);
Here's a generic functional solution:
pairs = (a, b) => a.map((_, i) => [a[i], b[i]])
flat = a => [].concat(...a)
valid = x => x === 0 || Boolean(x)
array_1 = [1, 2, 3, 4, 5, 6, 7, 8];
array_2 = [ , , , , 1, , 0, 1];
result = flat(
pairs(array_1, array_2)
.filter(x => x.every(valid))
)
console.log(result)
Works both ways, that is, it doesn't matter which array contains the null values. Also, you can redefine valid if there are other things to exclude.
As a bonus, if you replace pairs with zip, you can make it work for any number of arrays.
Having a matrix which contains many sub-arrays. Each array has the same length and each first element of them is a string followed by numeric elements having this form:
myArray = [
["revenues", 10, 20, 30],
["expenses", 1, 1, 1],
["expenses", 2, 3, 4],
["revenues", 5, 6, 7],
];
My goal is to combine them by string and compute the sum on each position. For the above example the result must be:
result = [
["revenues", 15, 26, 37],
["expenses", 3, 4, 5],
];
I tried to do it by mapping them by the value of the string and than compute sum for each position. It's only for the sub-arrays strings containing "revenues" in the first phase but still not working.
result = myArray.map(s => s[0].includes("revenues")).reduce(function (r, a) {
a.forEach(function (b, i) {
r[i] = (r[i] || 0) + b;
});
return r;
}, []);
Any suggestions?
You could find the sub array in the temporary result or add that array to the result set.
var array = [["revenues", 10, 20, 30], ["expenses", 1, 1, 1], ["expenses", 2, 3, 4], ["revenues", 5, 6, 7]],
result = array.reduce((r, a) => {
var sub = r.find(([key]) => key === a[0]);
if (!sub) {
return r.concat([a]);
}
a.forEach((v, i) => i && (sub[i] += v));
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var myArray = [
["revenues", 10, 20, 30],
["expenses", 1, 1, 1],
["expenses", 2, 3, 4],
["revenues", 5, 6, 7],
];
var result = myArray.reduce(function(acc, curr) {
if (acc[curr[0]]) {
acc[curr[0]] = acc[curr[0]].map(function(val, index) {
if (index) {
return val + curr[index];
}
return val
})
} else {
acc[curr[0]] = curr;
}
return acc
}, {})
console.log(Object.values(result))