Most efficient way to flatten Array<Array<T> | T> in JavaScript [duplicate] - javascript

This question already has answers here:
Merge/flatten an array of arrays
(84 answers)
Closed 3 years ago.
I want to create a function that accepts an array of both arrays and literals (or maybe objects) and flattens it to a single dimensional array. For example a valid input would be [5, [2, 3], 7, [9, 0, 1]], and the output of that input should be [5, 2, 3, 7, 9, 0, 1].
This is the code I have so far. There is nothing wrong with it, I just want to make sure it's as efficient as possible (it also needs to be es5 compatible).
function flattenArray(list) {
var result = [];
for (var index = 0; index < list.length; index++) {
result.push(list[index] instanceof Array ? list[index] : [list[index]]);
}
return [].concat.apply([], result);
}
console.log(flattenArray([5, [2, 3], 7, [9, 0, 1]]));

How about simply using Array.flat
function flattenArray(list) {
return list.flat()
}
console.log(flattenArray([5, [2, 3], 7, [9, 0, 1]]));
This seems to be second fastest ( based on the test link attached below ) and ES5 compatible
console.log([].concat.apply([],[5, [2, 3], 7, [9, 0, 1]]))
Performace test

Cocerning your code: There is no sense in wrapping single elements into arrays, .concat will handle them correctly, in other words:
[1].concat([2], 2)
just works, there is no need for wrapping 2 into [2]. That turns your code into a oneliner.

Related

Array spliting in JS not working as expected [duplicate]

This question already has answers here:
Array.prototype.fill() with object passes reference and not new instance
(7 answers)
Closed 1 year ago.
I have the following code, console.log is just to show what happens
function splitToChunks(array, parts) {
let result = new Array(parts).fill([]);
array.map((e,i)=> {console.log("r[",i%parts,"] gets -> ", e )|| result[i%parts].push(e)})
return result;
}
testing with arr = [0...11]
expected result would be:
[
[0, 4, 8],
[1, 5, 9],
[2, 6, 10],
[3, 7, 11],
]
The issue here is that the fill() array method passes by reference, not value, so it's actually the exact same "deep" object being passed to each sub-array, not new ones each time.
A quick workaround for this is to use fill() first and then map() the new array:
function splitToChunks(array, parts) {
let result = Array(parts).fill().map(e => []);
array.map((e,i) => { result[i % parts].push(e) });
return result;
}

How do I apply array methods to individual array that compose a two dimensional array in javascript?

As a two dimensional array is an array of arrays, I needed to apply array methods .unshift() and .pop() to each individual array in a 2D array of my JavaScript code.
Is there a way to do so? I know an individual member can be accessed by looping along a[i][j], but how do I obtain the individual array for applying methods to it?
Example: I have an array:
var a = [
[1,2,3]
[4,5,6]
[7,8,9]
]
Now in the first row I want to remove 3 from last and add 3 to the beginning giving me [3,1,2]. And do the same for all rows.
You can iterate over your array using .forEach(), and then for each element in your array (ie: each inner array), .pop() the last element from the end of your array, and then use .unshift(element) to prepend the element you just popped off you're array:
const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
a.forEach(innerArray => {
const last = innerArray.pop();
innerArray.unshift(last);
});
console.log(a);
The above can be implemented using a regular for loop if you find that easier to understand:
const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
for(let i = 0; i < a.length; i++) {
const innerArray = a[i];
const last = innerArray.pop();
innerArray.unshift(last);
}
console.log(a);
You can also do this by using .map(), which will produce a new array, leaving your original array a untouched:
const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
const a_new = a.map(inner => [inner.pop(), ...inner]);
console.log(a_new);
Map it. Functional programming is cool!
// to delete the first and last element of the inner array - `unshift` + `pop`
const result = someArray.map(innerArray => innerArray.slice(1, -1));

JS: Make new array form duplicate values [duplicate]

This question already has answers here:
Simplest code for array intersection in javascript
(40 answers)
Compute intersection of two arrays in JavaScript [duplicate]
(4 answers)
Finding matches between multiple JavaScript Arrays
(13 answers)
Closed 5 years ago.
Let's take two arrays for example:
a = [1, 2, 3, 4, 5]
b = [4, 5, 6, 7, 8]
Now there is duplicates as we see 4 and 5. How to make new array from them instead of getting rid of them. What is the easiest solution?
So new array should be like:
newArray = [4, 5]
Thank you guys in advance!
You can do it using Array.filter() and Array.includes()
let a = [1, 2, 3, 4, 5];
let b = [4, 5, 6, 7, 8];
let arr = a.filter(function(x){
return b.includes(x);
})
console.log(arr);

How to append new array to beginning of multi-dimensional array [duplicate]

This question already has answers here:
How can I add new array elements at the beginning of an array in JavaScript?
(12 answers)
Closed 5 years ago.
The community reviewed whether to reopen this question 9 months ago and left it closed:
Original close reason(s) were not resolved
I have a 2 dimensional array called vArr. It looks like follows...
vArr = [[1, 1], [2, 2], [3, 3]];
What I am trying to do, is move all the array elements along when a new array needs to be appended to the beginning of vArr, and then delete the last element of vArr to preserve its size (in this case 3). So for example, if a new element [4, 4] comes along that I want to append to vArr, the new vArr should look like this..
vArr = [[4, 4], [1, 1], [2, 2]];
[4, 4] has been appended to the beginning, all the other elements have moved along and any remaining elements past the vArr size of 3 (namely [3, 3]) have been removed. Here is my code so far...
var vArr = [[1, 1], [2, 3], [3, 3]];
var newv = [4, 4]; // New array to append
// My attempt at splicing newv to position 0 in vArr array without removing anything
vArr = vArr.splice(0, 0, newv);
// newv logs to the console successfully, however vArr is undefined for some reason
console.log(newv);
console.log(vArr);
// Get rid of final element (doesn't work because vArr is no longer defined from above)
vArr = vArr.pop();
I know there is probably something wrong with the syntax in the splicing line, but I have been unable to find any information online about what is wrong here. Does the splice method have to change if you are splicing arrays into 2D arrays? Or does it not work at all in this instance? Any help is greatly appreciated!
Here you go with the solution https://jsfiddle.net/fkz9ubug/
var vArr = [[1, 1], [2, 3], [3, 3]];
var newv = [4, 4];
vArr.unshift(newv)
console.log(vArr);
Documentation
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
https://www.w3schools.com/jsref/jsref_unshift.asp
The problem is with assigning the result of vArr.splice(0, 0, newv) back to vArr.
The splice function can also remove items from the array and the return value of splice() is those removed items.
So vArr = vArr.splice(0, 0, newv); should simply be vArr.splice(0, 0, newv);.
You can use unshift() for pushing the new array at the beginning of the original array, and pop() to remove the last element from the array:
var vArr = [[1, 1], [2, 2], [3, 3]];
var arrToPush = [4, 4];
vArr.unshift(arrToPush);
vArr.pop();
console.log(vArr);

Flatten a jagged multi dimensional array

I need help flattening an array like this:
[1,2,[2,3],[5,[6,1],4],7]
I want it to be something like
[1,2,2,3,5,6,1,4,7].
I have searched something like this, and found [].concat.apply, but it will only take care of the two dimensional arrays.
I also want to use an algorithm that will work for any jagged multi dimensional arrays. Please help. Thx
My recommendation would be to take a dependency on lodash and use the flattenDeep function.
_.flattenDeep([1,2,[2,3],[5,[6,1],4],7])
// [ 1, 2, 2, 3, 5, 6, 1, 4, 7 ]
If you want to write your own function, you might want to peek at the lodash implementation.
In pseudo-code, here's a recursive approach:
result = []
function flatten(array)
for each element in array
if element is array
flatten(element)
else
result.append(element)
EDIT
Here's a "by-hand" approach, though I'd definitely recommend relying on the better-tested lodash implementation.
function flatten(arr, result) {
if (result === undefined) {
result = [];
}
for (var i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
flatten(arr[i], result);
} else {
result.push(arr[i]);
}
}
return result;
}
console.log(flatten([1, 2, [2, 3], [5, [6, 1], 4], 7]));
// Output:
// [ 1, 2, 2, 3, 5, 6, 1, 4, 7 ]
You can wrap the concat.apply thing in a loop to handle deeply nested arrays:
while (a.some(Array.isArray))
a = [].concat.apply([], a)
or in the ES6 syntax:
while (a.some(Array.isArray))
a = [].concat(...a);

Categories

Resources