Using es6 spread to concat multiple arrays - javascript

We all know you can do:
let arr1 = [1,2,3];
let arr2 = [3,4,5];
let arr3 = [...arr1, ...arr2]; // [1,2,3,3,4,5]
But how do you make this dynamic to concat N arrays?

One option is to use reduce:
let arrs = [[1, 2], [3, 4], [5, 6]];
arrs.reduce((a, b) => [...a, ...b], []);
Of course, this is a slow solution (quadratic time). Alternatively, if you can use Lodash, _.flatten does exactly what you want, and does it more efficiently (linear time).
EDIT
Or, adapted from Xotic750's comment below,
[].concat(...arrs);
Which should be efficient (linear time).

Another option could be:
const nArrays = [
[1, 2, 3, 4, 5],
[6, 7, 8, 9],
[10, 11]
];
const flattened = [].concat(...nArrays);
console.log(flattened)

let fruits = ["apples", "bananas", "pears"];
let vegetables = ["corn", "potatoes", "carrots"];
let produce = [...fruits, ...vegetables];
console.log(produce);

Best option is to use FlatMap, which helps us to conact multiple arrays into one single array.
Example:
let arrs = [[1, 2], [3, 4], [5, 6]];
arrs.flatMap(a => a);
result will be
> (6) [1, 2, 3, 4, 5, 6]
Happy Coding...

Following solution works for me (spread operator in ES6):
let array = ['my','solution','works'];
let newArray = [];
let newArray2 = [];
newArray.push(...array); //adding to same array
newArray2.push([...array]); //adding as child/leaf/sub-array
console.log(newArray);
console.log(newArray2);

You can't do that with spread syntax alone, as spread syntax requires you to know how many arrays you are concatenating in advance. However, you could write the following function:
function concatN(...arguments) {
let accumulator = [];
for(let arg = 0; arg < arguments.length; arg = arg + 1) {
accumulator = [...accumulator, ...arguments[arg]];
}
return accumulator;
}
It probably won't be very efficient, though (repeated use of spread syntax is O(n²)). Using Array.prototype.concatwould be better. You can just do:
[].concat(all, of, your, arrays);

You can use spread element within for..of loop to concatenate array values to a single array
let arr1 = [1,2,3];
let arr2 = [3,4,5];
let arr3 = [];
for (let arr of [arr1, arr2 /* , arrN */]) arr3.push(...arr);
console.log(arr3);

You could use a recursive function and Array.prototype.concat
const concatN = (x,...xs) =>
x === undefined ? [] : x.concat(concatN(...xs))
console.log(concatN([1,2,3], [4,5,6], [7,8,9]))
// [1,2,3,4,5,6,7,8,9]
You can do the same thing using reduce and Array.prototype.concat. This is similar to the accepted answer but doesn't senselessly use spread syntax where x.concat(y) is perfectly acceptable (and likely heaps faster) in this case
const concatN = (...xs) =>
xs.reduce((x,y) => x.concat(y), [])
console.log(concatN([1,2,3], [4,5,6], [7,8,9]))
// [1,2,3,4,5,6,7,8,9]

We can resolve using es6 following way
function mergeTwo(arr1, arr2) {
let result = [...arr1, ...arr2];
return result.sort((a,b) => a-b);
}

let arr1 = [1,2,3];
let arr2 = [3,4,5];
let arrs = [arr1, arr2].flat(); // [1,2,3,3,4,5]
console.log(arrs);

Related

How to add extra values from 2 arrays to end of new array

For example, if I have 2 arrays being:
let array1 = [1,2,3]; and let array2 = [5,6,7,8,9], how would I create a new 3rd array that only contains the elements from array2 that are at the extra indexes (so the new array would only contain [8,9] since they are at index 3 and 4).
Thanks!
You can use the Javascript slice() function
arr1 = [1,2,3]
arr2=[5,6,7,8,9]
arr3 = arr2.slice(arr1.length , arr2.length)
console.log(arr3)
There are plenty of ways to do that, here's a solution that uses slice method with a negative index. That negative index is (array2.length - array1.length) * -1.
const array1 = [1, 2, 3],
array2 = [5, 6, 7, 8, 9],
sliceArray = (a1, a2) => a2.length <= a1.length ? [] : a2.slice((a2.length - a1.length) * -1)
console.log(sliceArray([], [])); // returns: []
console.log(sliceArray([1, 3, 6], [1, 2])); // returns: []
console.log(sliceArray(array1, array2)); // returns: [8, 9]
let array1 = [1,2,3,8,9];
let array2 = [5,6,7];
let array3=array1.length > array2.length ?array1.slice(array2.length,array1.length):array2.slice(array1.length,array2.length)
console.log(array3);
Use ternary operator and slice method
You can use a function that will find the longer array and slice it for you. That way, you don't need to know in advance which array is longer:
function collectExtra (arrayA, arrayB) {
if (arrayA.length === arrayB.length) return [];
const [shorter, longer] = [arrayA, arrayB]
.sort((a, b) => a.length - b.length);
return longer.slice(shorter.length);
}
const array1 = [1,2,3];
const array2 = [5,6,7,8,9];
const result = collectExtra(array1, array2);
console.log(result); // [8, 9]
const result2 = collectExtra(array2, array1);
console.log(result2); // [8, 9]

How to rearrange 3 arrays with according to the elements and return as one array?

I have 3 arrays. For example, given the arrays are
arr1 = [2, 7]
arr2 = [0, 1, 16]
arr3 = [3, 6, 9]
And I would like to rearrange them according to the numbers and output as an array.
result = ['arr2', 'arr2', 'arr1', 'arr3', 'arr3', 'arr1', 'arr3', 'arr2']
I think it might have something to do with looping, but I've no luck after struggling for a while. Is there any way to get the expected result?
You could move the values to an object and take another object for the indices and sort an array of key.
Then take the key at index zero and go on until the index is equal to the length of the array, then stop the iteration.
const
arr1 = [2, 7],
arr2 = [0, 1, 16],
arr3 = [3, 6, 9],
values = { arr1, arr2, arr3 },
result = [],
keys = Object.keys(values),
indices = Object.fromEntries(keys.map(k => [k, 0]));
while (true) {
keys.sort((a, b) => (values[a][indices[a]] ?? Number.MAX_VALUE) - (values[b][indices[b]] ?? Number.MAX_VALUE));
if (indices[keys[0]] === values[keys[0]].length) break;
result.push(keys[0]);
indices[keys[0]]++;
}
console.log(...result);
A shorter approach by mapping entries, sorting and mapping again.
const
arr1 = [2, 7],
arr2 = [0, 1, 16],
arr3 = [3, 6, 9],
result = Object
.entries({ arr1, arr2, arr3 })
.flatMap(([k, a]) => a.map(v => [k, v]))
.sort(([, a], [, b]) => a - b)
.map(([k]) => k);
console.log(...result);
Option 1. Allocate an array whose size is equal to the total count of elements in the 3 arrays. Populate the newly created array with the elements from your 3 small arrays. Then sort the created array.
Option 2. Merge 2 of the 3 arrays to produce a sorted array with elements from the chosen 2 small arrays. Then merged the sorted array from the previous step with the 3rd array to get the array that you need.
Not an elegant solution but maybe something like can help
arr1 = [2, 7]
arr2 = [0, 1, 16]
arr3 = [3, 6, 9]
let concatedArray = [...arr1, ...arr2, ...arr3].sort((a, b) => a - b);
let finalArr = []
concatedArray.forEach(val => {
let doesNumberExist = false;
let arrName = ''
doesNumberExist = arr1.includes(val);
arrName = 'arr1';
if (!doesNumberExist) {
doesNumberExist = arr2.includes(val);
arrName = 'arr2'
}
if (!doesNumberExist) {
doesNumberExist = arr3.includes(val);
arrName = 'arr3'
}
finalArr.push(arrName);
}
)
console.log(finalArr)

How filter simple multidimensional array with only numbers

I have a multidimensional array like this:
let arr = [ [1,2,3], [3,4,6], [4,5,7], [8,9,3]];
and I need to use only a filter function for filtering this array. I must filter the array and create a new array from the current inner arrays which contain the number 3:
let myArr = [ [1,2,3], [3,4,6], [4,5,7], [8,9,3]];
function getVal(value, arr){
for(let i in arr){
for(let j in arr[i]){
if(arr[i][j] == value){
return true;
}
}
}
}
let newArr = myArr.filter(getVal(3, myArr));
My code is not working. Actually, it's working, but I don`t see any result.
The expected result is like this:
newArr = [[1,2,3], [3,4,6], [8,9,3]];
All I have found are filter methods with objects.
You need a different style of the callback.
const contains = v => a => a.includes(v);
var array = [[1, 2, 3], [3, 4, 6], [4, 5, 7], [8, 9, 3]],
result = array.filter(contains(3));
console.log(result);
Assuming that it is 2 dimensional array. Use indexOf to check inside arrays:
myArr.filter((a)=> { return a.indexOf(3)>=0})
cont result = arr.filter(a => a.includes(3));

How use reduce() to concat an array and delete the items duplicated

I have a problem using the reduce function in JavaScript. My goal is to take an array of arrays and, using reduce, then concat all the values and delete the duplicates:
I have an array like this:
firstArray = [[1, 2],[2, 3, 4],[4, 5, 6]]
I need an array like this after apply reduce():
resultArray = [1, 2, 3, 4, 5, 6]
const arrayElements = [[1,2],[2,3,4],[5,6]];
const newArray = arrayElements.reduce((total, value) => {
return total.concat(value);
}, []);
This is the fragment that I have, this only concat all the values, this is to say, [1, 2, 2, 3, 4, 5, 6]
var num = [[1,2],[2,3,4],[5,6]];
var unique_numbers = [].concat(...num);
unique_numbers = Array.from(new Set(unique_numbers ));
You can use Set and flat
const array = [[1,2],[2,3,4],[5,6]];
const newArray = [...new Set(array.flat(Infinity))]
console.log(newArray)
Your reduce is correct, just add the data to a set, and convert the set to an array using spread syntax ...
const arrayElements = [[1,2],[2,3,4],[5,6]];
const newArray = [...new Set(arrayElements.reduce((total, value) => total.concat(value), []))];
console.log(newArray)
You can do this using Set:
const newArray = arrayElements.reduce((accum, arr) => [...accum, ..arr], [])
const arrNoDupes = [...new Set(newArray)]
or using filter:
const newArray = arrayElements.reduce((accum, arr) => [
...accum
...arr.filter(value => !accum.includes(value))
], [])
These are just two ways you can do what you want to achieve.
Here is the old fashioned ES5 way in case browser support is a concern.
var arrayElements = [[1,2],[2,3,4],[5,6]];
var newArray = arrayElements.reduce(function(total, value){
return total.concat(value).filter(function (x, i, a) {
return a.indexOf(x) == i;
});
}, []);
console.log(newArray)

Create an array using longest length of arrays passed to a function, using Math.max?

I am trying to build a new array with a length that is equal to the longest array that is passed to a function. There can be an infinite number of arrays passed to the function, which is why I am trying to use Math.max.
I worked this up that uses loops...:
function sumInternalValues() {
let arrays = Array.from(arguments);
let longest = 0;
arrays.forEach(arr => {
longest = (arr.length > longest) ? arr.length : longest;
})
let newArr = new Array(longest);
//... do other things but for sake of this question, return here now
return newArr.length;
}
let arr1 = [1, 2, 3, 4];
let arr2 = [5, 6, 7, 8, 9, 10];
console.log(sumInternalValues(arr1, arr2));
But how can I get Math.max to work with this instead?
function sumInternalValues() {
let newArr = new Array(Math.max.apply(Math, arguments.length?));
}
Note: I will be answering my own question based on the guidelines here. I spent a fair amount of time trying to get this and didn't find much support on SO.
You can do this by capturing the arguments as an array using array.from(), and then mapping the resulting array to get just lengths. And then apply that array to the Math.max function:
function sumInternalValues() {
let args = Array.from(arguments);
let newArr = new Array(Math.max.apply(Math, args.map(a => a.length)));
// ... do some other things, but for the sake of this question, return here
return newArr.length
}
let arr1 = [1, 2, 3, 4];
let arr2 = [5, 6, 7, 8, 9, 10];
console.log(sumInternalValues(arr1, arr2));
A dense array:
let denseArr = Object.assign([], arr1, arr2).fill(undefined);
A sparse array:
let sparseArr = [];
sparseArr.length = Math.max(...[arr1, arr2].map(arr => arr.length));

Categories

Resources