I have a JavaScript array like:
[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
How would I go about merging the separate inner arrays into one like:
["$6", "$12", "$25", ...]
I have a JavaScript array like:
[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
How would I go about merging the separate inner arrays into one like:
["$6", "$12", "$25", ...]
ES2019 introduced the Array.prototype.flat()
method which you could use to flatten the arrays. It is compatible with most environments, although it is only available in Node.js starting with version 11, and not at all in Internet Explorer.
const arrays = [
["$6"],
["$12"],
["$25"],
["$25"],
["$18"],
["$22"],
["$10"]
];
const merge3 = arrays.flat(1); //The depth level specifying how deep a nested array structure should be flattened. Defaults to 1.
console.log(merge3);
For older browsers, you can use Array.prototype.concat
to merge arrays:
var arrays = [
["$6"],
["$12"],
["$25"],
["$25"],
["$18"],
["$22"],
["$10"]
];
var merged = [].concat.apply([], arrays);
console.log(merged);
Using the apply
method of concat
will just take the second parameter as an array, so the last line is identical to this:
var merged = [].concat(["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]);
Array.prototype.concat.apply([], arrays)
. –
Hammond var merged = [].concat(...arrays)
–
Jut Array.prototype.concat(...arrays)
. This version works with Typescript's 2.3.0 --strict
mode. Doesn't work with nested arrays (it's not recursive). –
Giamo [].concat(...arrays)
also works in Typescript –
Wildman var merged = [].concat.apply([], arrays);
, thisArg is set to an empty array? –
Aedile [].concat(arrayA, arrayB)
–
Punkie [].
I get an error back saying "Argument of type 'number[]' is not assignable to parameter of type 'ConcatArray<never>'. (I'm merging a 2-dimensional array of numbers.) The error resolves and I get the expected output if I change this to new Array().concat(...arrays)
–
Culmiferous [].concat(...arrays).length
this helped me do a count / empty check without changing original array. Thanks! –
Senhauser flat()
goes more levels deep. –
Ruth Here's a short function that uses some of the newer JavaScript array methods to flatten an n-dimensional array.
function flatten(arr) {
return arr.reduce(function (flat, toFlatten) {
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
}, []);
}
Usage:
flatten([[1, 2, 3], [4, 5]]); // [1, 2, 3, 4, 5]
flatten([[[1, [1.1]], 2, 3], [4, 5]]); // [1, 1.1, 2, 3, 4, 5]
flat
in the first call to the anonymous function passed to reduce
. If it is not specified, then the first call to reduce
binds the first value out of the array to flat
, which would eventually result in 1
being bound to flat
in both the examples. 1.concat
is not a function. –
Sacrificial const flatten = (arr) => arr.reduce((flat, next) => flat.concat(next), []);
–
Dhruv const flatten = (arr) => arr.reduce((flat, next) => flat.concat(Array.isArray(next) ? flatten(next) : next), []);
–
Paba concat
is supposed to create a new array, but the runtimes can optimize just like hey already do e.g. for lots of kinds of string operations. If they detect the array is immediately discarded, and they can even limit the detection to the reduce
function specifically, they can reuse the same array internally. Fort your interviews, I would say anybody who thinks that the observable behavior of JS code always is exactly the same as what the runtime does internally should maybe not be rejected but definitely educated - this stuff may change any time. –
Wolgast There is a confusingly hidden method, which constructs a new array without mutating the original one:
var oldArray = [[1],[2,3],[4]];
var newArray = Array.prototype.concat.apply([], oldArray);
console.log(newArray); // [ 1, 2, 3, 4 ]
[].concat(...[ [1],[2,3],[4] ])
. –
Studhorse flat = (e) => Array.isArray(e)? [].concat.apply([], e.map(flat)) : e
–
Somewhere It can be best done by javascript reduce function.
var arrays = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]];
arrays = arrays.reduce(function(a, b){
return a.concat(b);
}, []);
Or, with ES2015:
arrays = arrays.reduce((a, b) => a.concat(b), []);
arrays.reduce((flatten, arr) => [...flatten, ...arr])
–
Cottle There's a new native method called flat to do this exactly.
(As of late 2019, flat
is now published in the ECMA 2019 standard, and core-js@3
(babel's library) includes it in their polyfill library)
const arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
// Flatten 2 levels deep
const arr3 = [2, 2, 5, [5, [5, [6]], 7]];
arr3.flat(2);
// [2, 2, 5, 5, 5, [6], 7];
// Flatten all levels
const arr4 = [2, 2, 5, [5, [5, [6]], 7]];
arr4.flat(Infinity);
// [2, 2, 5, 5, 5, 6, 7];
flat()
. But that's not a big deal, Chromium Edge is already available so you can tell your users to upgrade to it, and if nothing else the next Windows 10 update will include Chromium Edge by default. –
Revisal flat
polyfill outside of babel. And then flatMap
polyfill can be return Array.isArray(array) ? array.map(callback).flat() : array;
. If you need map
as well, MDN has a map
poly. Or just transpile your code like most folk in 2020. ;^D –
Procuration Most of the answers here don't work on huge (e.g. 200 000 elements) arrays, and even if they do, they're slow.
Here is the fastest solution, which works also on arrays with multiple levels of nesting:
const flatten = function(arr, result = []) {
for (let i = 0, length = arr.length; i < length; i++) {
const value = arr[i];
if (Array.isArray(value)) {
flatten(value, result);
} else {
result.push(value);
}
}
return result;
};
flatten(Array(200000).fill([1]));
It handles huge arrays just fine. On my machine this code takes about 14 ms to execute.
flatten(Array(2).fill(Array(2).fill(Array(2).fill([1]))));
It works with nested arrays. This code produces [1, 1, 1, 1, 1, 1, 1, 1]
.
flatten([1, [1], [[1]]]);
It doesn't have any problems with flattening arrays like this one.
RangeError: Maximum call stack size exceeded
). For 20 000-element array it takes 2-5 milliseconds. –
Pak But in what real-world situation would you have arrays with more than a few levels of nesting?
-> When you design grammars, their parsers/lexers can generate deeply nested arrays easily. –
Martinmas Update: it turned out that this solution doesn't work with large arrays. It you're looking for a better, faster solution, check out this answer.
function flatten(arr) {
return [].concat(...arr)
}
Is simply expands arr
and passes it as arguments to concat()
, which merges all the arrays into one. It's equivalent to [].concat.apply([], arr)
.
You can also try this for deep flattening:
function deepFlatten(arr) {
return flatten( // return shalowly flattened array
arr.map(x=> // with each x in array
Array.isArray(x) // is x an array?
? deepFlatten(x) // if yes, return deeply flattened x
: x // if no, return just x
)
)
}
See demo on JSBin.
References for ECMAScript 6 elements used in this answer:
Side note: methods like find()
and arrow functions are not supported by all browsers, but it doesn't mean that you can't use these features right now. Just use Babel — it transforms ES6 code into ES5.
apply
in this way, I removed my comments from yours. I still think using apply
/spread this way is bad advise, but since no one cares... –
Carolus const flatten = arr => [].concat(...arr)
–
Abrasive You can use Underscore:
var x = [[1], [2], [3, 4]];
_.flatten(x); // => [1, 2, 3, 4]
true
for the second argument. –
Mattiematting Generic procedures mean we don't have to rewrite complexity each time we need to utilize a specific behaviour.
concatMap
(or flatMap
) is exactly what we need in this situation.
// concat :: ([a],[a]) -> [a]
const concat = (xs,ys) =>
xs.concat (ys)
// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = f => xs =>
xs.map(f).reduce(concat, [])
// id :: a -> a
const id = x =>
x
// flatten :: [[a]] -> [a]
const flatten =
concatMap (id)
// your sample data
const data =
[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
console.log (flatten (data))
And yes, you guessed it correctly, it only flattens one level, which is exactly how it should work
Imagine some data set like this
// Player :: (String, Number) -> Player
const Player = (name,number) =>
[ name, number ]
// team :: ( . Player) -> Team
const Team = (...players) =>
players
// Game :: (Team, Team) -> Game
const Game = (teamA, teamB) =>
[ teamA, teamB ]
// sample data
const teamA =
Team (Player ('bob', 5), Player ('alice', 6))
const teamB =
Team (Player ('ricky', 4), Player ('julian', 2))
const game =
Game (teamA, teamB)
console.log (game)
// [ [ [ 'bob', 5 ], [ 'alice', 6 ] ],
// [ [ 'ricky', 4 ], [ 'julian', 2 ] ] ]
Ok, now say we want to print a roster that shows all the players that will be participating in game
…
const gamePlayers = game =>
flatten (game)
gamePlayers (game)
// => [ [ 'bob', 5 ], [ 'alice', 6 ], [ 'ricky', 4 ], [ 'julian', 2 ] ]
If our flatten
procedure flattened nested arrays too, we'd end up with this garbage result …
const gamePlayers = game =>
badGenericFlatten(game)
gamePlayers (game)
// => [ 'bob', 5, 'alice', 6, 'ricky', 4, 'julian', 2 ]
That's not to say sometimes you don't want to flatten nested arrays, too – only that shouldn't be the default behaviour.
We can make a deepFlatten
procedure with ease …
// concat :: ([a],[a]) -> [a]
const concat = (xs,ys) =>
xs.concat (ys)
// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = f => xs =>
xs.map(f).reduce(concat, [])
// id :: a -> a
const id = x =>
x
// flatten :: [[a]] -> [a]
const flatten =
concatMap (id)
// deepFlatten :: [[a]] -> [a]
const deepFlatten =
concatMap (x =>
Array.isArray (x) ? deepFlatten (x) : x)
// your sample data
const data =
[0, [1, [2, [3, [4, 5], 6]]], [7, [8]], 9]
console.log (flatten (data))
// [ 0, 1, [ 2, [ 3, [ 4, 5 ], 6 ] ], 7, [ 8 ], 9 ]
console.log (deepFlatten (data))
// [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
There. Now you have a tool for each job – one for squashing one level of nesting, flatten
, and one for obliterating all nesting deepFlatten
.
Maybe you can call it obliterate
or nuke
if you don't like the name deepFlatten
.
Don't iterate twice !
Of course the above implementations are clever and concise, but using a .map
followed by a call to .reduce
means we're actually doing more iterations than necessary
Using a trusty combinator I'm calling mapReduce
helps keep the iterations to a minium; it takes a mapping function m :: a -> b
, a reducing function r :: (b,a) ->b
and returns a new reducing function - this combinator is at the heart of transducers; if you're interested, I've written other answers about them
// mapReduce = (a -> b, (b,a) -> b, (b,a) -> b)
const mapReduce = (m,r) =>
(acc,x) => r (acc, m (x))
// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = f => xs =>
xs.reduce (mapReduce (f, concat), [])
// concat :: ([a],[a]) -> [a]
const concat = (xs,ys) =>
xs.concat (ys)
// id :: a -> a
const id = x =>
x
// flatten :: [[a]] -> [a]
const flatten =
concatMap (id)
// deepFlatten :: [[a]] -> [a]
const deepFlatten =
concatMap (x =>
Array.isArray (x) ? deepFlatten (x) : x)
// your sample data
const data =
[ [ [ 1, 2 ],
[ 3, 4 ] ],
[ [ 5, 6 ],
[ 7, 8 ] ] ]
console.log (flatten (data))
// [ [ 1. 2 ], [ 3, 4 ], [ 5, 6 ], [ 7, 8 ] ]
console.log (deepFlatten (data))
// [ 1, 2, 3, 4, 5, 6, 7, 8 ]
concat
itself doesn't blow up the stack, only ...
and apply
does (along with very large arrays). I didn't see it. I just feel terrible right now. –
Carolus concat
in Javascript has a different meaning than in Haskell. Haskell's concat
([[a]] -> [a]
) would be called flatten
in Javascript and is implemented as foldr (++) []
(Javascript: foldr(concat) ([])
assuming curried functions). Javascript's concat
is a weird append ((++)
in Haskell), which can handle both [a] -> [a] -> [a]
and a -> [a] -> [a]
. –
Carolus flatMap
, because that is exactly what concatMap
is: The bind
instance of the list
monad. concatpMap
is implemented as foldr ((++) . f) []
. Translated into Javascript: const flatMap = f => foldr(comp(concat) (f)) ([])
. This is of course similar to your implementation without comp
. –
Carolus To flatten an array of single element arrays, you don't need to import a library, a simple loop is both the simplest and most efficient solution :
for (var i = 0; i < a.length; i++) {
a[i] = a[i][0];
}
To downvoters: please read the question, don't downvote because it doesn't suit your very different problem. This solution is both the fastest and simplest for the asked question.
['foo', ['bar']]
to ['f', 'bar']
. –
Tranquilize A solution for the more general case, when you may have some non-array elements in your array.
function flattenArrayOfArrays(a, r){
if(!r){ r = []}
for(var i=0; i<a.length; i++){
if(a[i].constructor == Array){
flattenArrayOfArrays(a[i], r);
}else{
r.push(a[i]);
}
}
return r;
}
flattenArrayOfArrays (arr, 10)
or this flattenArrayOfArrays(arr, [1,[3]]);
- those second arguments are added to the output. –
Houphouetboigny You can also try the new Array.flat()
method. It works in the following manner:
let arr = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]].flat()
console.log(arr);
The flat()
method creates a new array with all sub-array elements concatenated into it recursively up to the 1 layer of depth (i.e. arrays inside arrays)
If you want to also flatten out 3 dimensional or even higher dimensional arrays you simply call the flat method multiple times. For example (3 dimensions):
let arr = [1,2,[3,4,[5,6]]].flat().flat().flat();
console.log(arr);
Array.flat()
method is relatively new. Older browsers like ie might not have implemented the method. If you want you code to work on all browsers you might have to transpile your JS to an older version. Check for MDN web docs for current browser compatibility.
Infinity
argument. Like this: arr.flat(Infinity)
–
Retharethink Another ECMAScript 6 solution in functional style:
Declare a function:
const flatten = arr => arr.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
);
and use it:
flatten( [1, [2,3], [4,[5,[6]]]] ) // -> [1,2,3,4,5,6]
const flatten = arr => arr.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
);
console.log( flatten([1, [2,3], [4,[5],[6,[7,8,9],10],11],[12],13]) )
Consider also a native function Array.prototype.flat() (proposal for ES6) available in last releases of modern browsers. Thanks to @(Константин Ван) and @(Mark Amery) mentioned it in the comments.
The flat
function has one parameter, specifying the expected depth of array nesting, which equals 1
by default.
[1, 2, [3, 4]].flat(); // -> [1, 2, 3, 4]
[1, 2, [3, 4, [5, 6]]].flat(); // -> [1, 2, 3, 4, [5, 6]]
[1, 2, [3, 4, [5, 6]]].flat(2); // -> [1, 2, 3, 4, 5, 6]
[1, 2, [3, 4, [5, 6]]].flat(Infinity); // -> [1, 2, 3, 4, 5, 6]
let arr = [1, 2, [3, 4]];
console.log( arr.flat() );
arr = [1, 2, [3, 4, [5, 6]]];
console.log( arr.flat() );
console.log( arr.flat(1) );
console.log( arr.flat(2) );
console.log( arr.flat(Infinity) );
RangeError: Maximum call stack size exceeded
–
Elisa [].concat.apply([], arrays);
–
Elisa .flat()
! –
Subtorrid flat
isn't part of ES6. It's not even part of ES9. It's a proposal, not yet part of the ECMAScript spec, and not yet available in all major JavaScript environments. –
Haematin What about using reduce(callback[, initialValue])
method of JavaScript 1.8
list.reduce((p,n) => p.concat(n),[]);
Would do the job.
const common = arr.reduce((a, b) => [...a, ...b], [])
You can use Array.flat()
with Infinity
for any depth of nested array.
var arr = [ [1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]], [[1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]]] ];
let flatten = arr.flat(Infinity)
console.log(flatten)
check here for browser compatibility
See lodash flatten, underscore flatten (shallow true
)
function flatten(arr) {
return arr.reduce((acc, e) => acc.concat(e), []);
}
function flatten(arr) {
return [].concat.apply([], arr);
}
Tested with
test('already flatted', () => {
expect(flatten([1, 2, 3, 4, 5])).toEqual([1, 2, 3, 4, 5]);
});
test('flats first level', () => {
expect(flatten([1, [2, [3, [4]], 5]])).toEqual([1, 2, [3, [4]], 5]);
});
See lodash flattenDeep, underscore flatten
function flattenDeep(arr) {
return arr.reduce((acc, e) => Array.isArray(e) ? acc.concat(flattenDeep(e)) : acc.concat(e), []);
}
Tested with
test('already flatted', () => {
expect(flattenDeep([1, 2, 3, 4, 5])).toEqual([1, 2, 3, 4, 5]);
});
test('flats', () => {
expect(flattenDeep([1, [2, [3, [4]], 5]])).toEqual([1, 2, 3, 4, 5]);
});
Array.prototype.concat.apply([], arr)
because you create an extra array just to get to the concat
function. Runtimes may or may not optimize it away when they run it, but accessing the function on the prototype doesn't look any uglier than this already is in any case. –
Wolgast Using the spread operator:
const input = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]];
const output = [].concat(...input);
console.log(output); // --> ["$6", "$12", "$25", "$25", "$18", "$22", "$10"]
Please note: When Function.prototype.apply
([].concat.apply([], arrays)
) or the spread operator ([].concat(...arrays)
) is used in order to flatten an array, both can cause stack overflows for large arrays, because every argument of a function is stored on the stack.
Here is a stack-safe implementation in functional style that weighs up the most important requirements against one another:
// small, reusable auxiliary functions:
const foldl = f => acc => xs => xs.reduce(uncurry(f), acc); // aka reduce
const uncurry = f => (a, b) => f(a) (b);
const concat = xs => y => xs.concat(y);
// the actual function to flatten an array - a self-explanatory one-line:
const flatten = xs => foldl(concat) ([]) (xs);
// arbitrary array sizes (until the heap blows up :D)
const xs = [[1,2,3],[4,5,6],[7,8,9]];
console.log(flatten(xs));
// Deriving a recursive solution for deeply nested arrays is trivially now
// yet more small, reusable auxiliary functions:
const map = f => xs => xs.map(apply(f));
const apply = f => a => f(a);
const isArray = Array.isArray;
// the derived recursive function:
const flattenr = xs => flatten(map(x => isArray(x) ? flattenr(x) : x) (xs));
const ys = [1,[2,[3,[4,[5],6,],7],8],9];
console.log(flattenr(ys));
As soon as you get used to small arrow functions in curried form, function composition and higher order functions, this code reads like prose. Programming then merely consists of putting together small building blocks that always work as expected, because they don't contain any side effects.
const flatten = (arr) => arr.reduce((a, b) => a.concat(b), []);
saves you visual garbage and explanation to your teammates why you need 3 extra functions and some function calls too. –
Hayse I recommend a space-efficient generator function:
function* flatten(arr) {
if (!Array.isArray(arr)) yield arr;
else for (let el of arr) yield* flatten(el);
}
// Example:
console.log(...flatten([1,[2,[3,[4]]]])); // 1 2 3 4
If desired, create an array of flattened values as follows:
let flattened = [...flatten([1,[2,[3,[4]]]])]; // [1, 2, 3, 4]
...
to iterate through the generator. –
Sympathetic If you only have arrays with 1 string element:
[["$6"], ["$12"], ["$25"], ["$25"]].join(',').split(',');
will do the job. Bt that specifically matches your code example.
['$4', ["$6"], ["$12"], ["$25"], ["$25", "$33", ['$45']]].join(',').split(',')
–
Devoir [1,4, [45, 't', ['e3', 6]]].toString().split(',')
---- or ----- [1,4, [45, 't', ['e3', 6], false]].toString().split(',')
–
Chatelaine I have done it using recursion and closures
function flatten(arr) {
var temp = [];
function recursiveFlatten(arr) {
for(var i = 0; i < arr.length; i++) {
if(Array.isArray(arr[i])) {
recursiveFlatten(arr[i]);
} else {
temp.push(arr[i]);
}
}
}
recursiveFlatten(arr);
return temp;
}
A Haskellesque approach
function flatArray([x,...xs]){
return x ? [...Array.isArray(x) ? flatArray(x) : [x], ...flatArray(xs)] : [];
}
var na = [[1,2],[3,[4,5]],[6,7,[[[8],9]]],10];
fa = flatArray(na);
console.log(fa);
if you use lodash, you can just use its flatten
method: https://lodash.com/docs/4.17.14#flatten
The nice thing about lodash is that it also has methods to flatten the arrays:
i) recursively: https://lodash.com/docs/4.17.14#flattenDeep
ii) upto n levels of nesting: https://lodash.com/docs/4.17.14#flattenDepth
For example
const _ = require("lodash");
const pancake = _.flatten(array)
ES6 way:
const flatten = arr => arr.reduce((acc, next) => acc.concat(Array.isArray(next) ? flatten(next) : next), [])
const a = [1, [2, [3, [4, [5]]]]]
console.log(flatten(a))
ES5 way for flatten
function with ES3 fallback for N-times nested arrays:
var flatten = (function() {
if (!!Array.prototype.reduce && !!Array.isArray) {
return function(array) {
return array.reduce(function(prev, next) {
return prev.concat(Array.isArray(next) ? flatten(next) : next);
}, []);
};
} else {
return function(array) {
var arr = [];
var i = 0;
var len = array.length;
var target;
for (; i < len; i++) {
target = array[i];
arr = arr.concat(
(Object.prototype.toString.call(target) === '[object Array]') ? flatten(target) : target
);
}
return arr;
};
}
}());
var a = [1, [2, [3, [4, [5]]]]];
console.log(flatten(a));
I was goofing with ES6 Generators the other day and wrote this gist. Which contains...
function flatten(arrayOfArrays=[]){
function* flatgen() {
for( let item of arrayOfArrays ) {
if ( Array.isArray( item )) {
yield* flatten(item)
} else {
yield item
}
}
}
return [...flatgen()];
}
var flatArray = flatten([[1, [4]],[2],[3]]);
console.log(flatArray);
Basically I'm creating a generator that loops over the original input array, if it finds an array it uses the yield* operator in combination with recursion to continually flatten the internal arrays. If the item is not an array it just yields the single item. Then using the ES6 Spread operator (aka splat operator) I flatten out the generator into a new array instance.
I haven't tested the performance of this, but I figure it is a nice simple example of using generators and the yield* operator.
But again, I was just goofing so I'm sure there are more performant ways to do this.
just the best solution without lodash
let flatten = arr => [].concat.apply([], arr.map(item => Array.isArray(item) ? flatten(item) : item))
I would rather transform the whole array, as-is, to a string, but unlike other answers, would do that using JSON.stringify
and not use the toString()
method, which produce an unwanted result.
With that JSON.stringify
output, all that's left is to remove all brackets, wrap the result with start & ending brackets yet again, and serve the result with JSON.parse
which brings the string back to "life".
var arr = ["abc",[[[6]]],["3,4"],"2"];
var s = "[" + JSON.stringify(arr).replace(/\[|]/g,'') +"]";
var flattened = JSON.parse(s);
console.log(flattened)
["345", "2", "3,4", "2"]
instead of separating each of those values to separate indices –
Stoughton "3,4"
. –
Fiora // using Es6 flat()
let arr = [1,[2,[3,[4,[5,[6,7],8],9],10]]]
console.log(arr.flat(Infinity))
// using Es6 reduce()
let flatIt = (array) => array.reduce(
(x, y) => x.concat(Array.isArray(y) ? flatIt(y) : y), []
)
console.log(flatIt(arr))
// using recursion
function myFlat(array) {
let flat = [].concat(...array);
return flat.some(Array.isArray) ? myFlat(flat) : flat;
}
console.log(myFlat(arr));
// using string manipulation
let strArr = arr.toString().split(',');
for(let i=0;i<strArr.length;i++)
strArr[i]=parseInt(strArr[i]);
console.log(strArr)
I think array.flat(Infinity) is a perfect solution. But flat function is a relatively new function and may not run in older versions of browsers. We can use recursive function for solving this.
const arr = ["A", ["B", [["B11", "B12", ["B131", "B132"]], "B2"]], "C", ["D", "E", "F", ["G", "H", "I"]]]
const flatArray = (arr) => {
const res = []
for (const item of arr) {
if (Array.isArray(item)) {
const subRes = flatArray(item)
res.push(...subRes)
} else {
res.push(item)
}
}
return res
}
console.log(flatArray(arr))
You can use "join()" and "split()":
let arrs = [
["$6"],
["$12"],
["$25"],
["$25"],
["$18"],
["$22"],
["$10"]
];
let newArr = arrs.join(",").split(",");
console.log(newArr); // ["$6", "$12", "$25", "$25", "$18", "$22", "$10"]
In addition, you can use "toString()" and "split()" as well:
let arrs = [
["$6"],
["$12"],
["$25"],
["$25"],
["$18"],
["$22"],
["$10"]
];
let newArr = arrs.toString().split(",");
console.log(newArr); // ["$6", "$12", "$25", "$25", "$18", "$22", "$10"]
However, both two ways above don't work properly if string contains commas:
"join()" and "split()":
let arrs = [
["$,6"],
["$,12"],
["$2,5"],
["$2,5"],
[",$18"],
["$22,"],
["$,1,0"]
];
let newArr = arrs.join(",").split(",");
console.log(newArr);
// ["$", "6", "$", "12", "$2", "5", "$2", "5", "", "$18", "$22", "", "$", "1", "0"]
"toString()" and "split()":
let arrs = [
["$,6"],
["$,12"],
["$2,5"],
["$2,5"],
[",$18"],
["$22,"],
["$,1,0"]
];
let newArr = arrs.toString().split(",");
console.log(newArr);
// ["$", "6", "$", "12", "$2", "5", "$2", "5", "", "$18", "$22", "", "$", "1", "0"]
That's not hard, just iterate over the arrays and merge them:
var result = [], input = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"]];
for (var i = 0; i < input.length; ++i) {
result = result.concat(input[i]);
}
Here is the recursive way...
function flatten(arr){
let newArray = [];
for(let i=0; i< arr.length; i++){
if(Array.isArray(arr[i])){
newArray = newArray.concat(flatten(arr[i]))
}else{
newArray.push(arr[i])
}
}
return newArray;
}
console.log(flatten([1, 2, 3, [4, 5] ])); // [1, 2, 3, 4, 5]
console.log(flatten([[[[1], [[[2]]], [[[[[[[3]]]]]]]]]])) // [1,2,3]
console.log(flatten([[1],[2],[3]])) // [1,2,3]
function flatten(input) {
let result = [];
function extractArrayElements(input) {
for(let i = 0; i < input.length; i++){
if(Array.isArray(input[i])){
extractArrayElements(input[i]);
}else{
result.push(input[i]);
}
}
}
extractArrayElements(input);
return result;
}
// let input = [1,2,3,[4,5,[44,7,8,9]]];
// console.log(flatten(input));
// output [1,2,3,4,5,6,7,8,9]
Here is the fastest solution in Typescript, which works also on arrays with multiple levels of nesting:
export function flatten<T>(input: Array<any>, output: Array<T> = []): Array<T> {
for (const value of input) {
Array.isArray(value) ? flatten(value, output) : output.push(value);
}
return output;
}
and than:
const result = flatten<MyModel>(await Promise.all(promises));
const arr = [1, 2, [3, 4]];
arr.reduce((acc, val) => acc.concat(val), []);
Well if your coding environment supports ES6 (ES2015), you need not write any recursive functions or use array methods like map, reduce etc.
A simple spread operator (...) will help you flatten an Array of arrays into a single Array
eg:
const data = [[1, 2, 3], [4, 5],[2]]
let res = []
data.forEach(curSet=>{
res = [...res,...curSet]
})
console.log(res) //[1, 2, 3, 4, 5, 2]
I am using this method to flat mixed arrays: (which seems easiest for me). Wrote it in longer version to explain steps.
function flattenArray(deepArray) {
// check if Array
if(!Array.isArray(deepArray)) throw new Error('Given data is not an Array')
const flatArray = deepArray.flat() // flatten array
const filteredArray = flatArray.filter(item => !!item) // filter by Boolean
const uniqueArray = new Set(filteredArray) // filter by unique values
return [...uniqueArray] // convert Set into Array
}
// shorter version:
const flattenArray = (deepArray) => [...new Set(deepArray.flat().filter(item=>!!item))]
flattenArray([4,'a', 'b', [3, 2, undefined, 1], [1, 4, null, 5]])) // 4,'a','b',3,2,1,5
Use of [].flat(Infinity) method
const nestedArray = [1,[2,[3],[4,[5,[6,[7]]]]]]
const flatArray = nestedArray.flat(Infinity)
console.log(flatArray)
It looks like this looks like a job for RECURSION!
Code:
var flatten = function(toFlatten) {
var isArray = Object.prototype.toString.call(toFlatten) === '[object Array]';
if (isArray && toFlatten.length > 0) {
var head = toFlatten[0];
var tail = toFlatten.slice(1);
return flatten(head).concat(flatten(tail));
} else {
return [].concat(toFlatten);
}
};
Usage:
flatten([1,[2,3],4,[[5,6],7]]);
// Result: [1, 2, 3, 4, 5, 6, 7]
flatten(new Array(15000).fill([1]))
throws Uncaught RangeError: Maximum call stack size exceeded
and freezed my devTools for 10 seconds –
Flexible I propose two short solutions without recursion. They are not optimal from a computational complexity point of view, but work fine in average cases:
let a = [1, [2, 3], [[4], 5, 6], 7, 8, [9, [[10]]]];
// Solution #1
while (a.find(x => Array.isArray(x)))
a = a.reduce((x, y) => x.concat(y), []);
// Solution #2
let i = a.findIndex(x => Array.isArray(x));
while (i > -1)
{
a.splice(i, 1, ...a[i]);
i = a.findIndex(x => Array.isArray(x));
}
The logic here is to convert input array to string and remove all brackets([]) and parse output to array. I'm using ES6 template feature for this.
var x=[1, 2, [3, 4, [5, 6,[7], 9],12, [12, 14]]];
var y=JSON.parse(`[${JSON.stringify(x).replace(/\[|]/g,'')}]`);
console.log(y)
const flatten = function (A) { return A .toString() .split(',') .reduce( (a,c) => { let i = parseFloat(c); c = (!Number.isNaN(i)) ? i : c; a.push(c); return a; }, []);
–
Presidentship Here is a version in Typescript based on the answer by artif3x, with a bonus implementation of flatMap
for Scala fans.
function flatten<T>(items: T[][]): T[] {
return items.reduce((prev, next) => prev.concat(next), []);
}
function flatMap<T, U>(items: T[], f: (t: T) => U[]): U[] {
return items.reduce((prev, next) => prev.concat(f(next)), new Array<U>());
}
Here's another deep flatten for modern browsers:
function flatten(xs) {
xs = Array.prototype.concat.apply([], xs);
return xs.some(Array.isArray) ? flatten(xs) : xs;
};
Nowadays the best and easy way to do this is joining and spliting the array like this.
var multipleArrays = [["$6","$Demo"], ["$12",["Multi","Deep"]], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]]
var flattened = multipleArrays.join().split(",")
This solution works with multiple levels and is also oneliner.
EDIT for ECMAScript 6
Since ECMAScript 6 has been standardized, you can change the operation [].concat.apply([], arrays);
for [].concat(...arrays);
var flattened = [].concat(...input);
EDIT Most Efficient solution
The most efficient way to solve the problem is using a loop. You can compare the "ops/sec" velocity here
var flattened=[];
for (var i=0; i<input.length; ++i) {
var current = input[i];
for (var j=0; j<current.length; ++j)
flattened.push(current[j]);
}
Hope It Helps
[[","]].join().split(",")
doesn't give desired result. –
Pak const flatten = array => array.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
Per request, Breaking down the one line is basically having this.
function flatten(array) {
// reduce traverses the array and we return the result
return array.reduce(function(acc, b) {
// if is an array we use recursion to perform the same operations over the array we found
// else we just concat the element to the accumulator
return acc.concat( Array.isArray(b) ? flatten(b) : b);
}, []); // we initialize the accumulator on an empty array to collect all the elements
}
Array.isArray(b)
in to b.length
and add a Array.from(array)
after the return instead of array
. –
Fingered Just to add to the great solutions. I used recursion to solve this.
const flattenArray = () => {
let result = [];
return function flatten(arr) {
for (let i = 0; i < arr.length; i++) {
if (!Array.isArray(arr[i])) {
result.push(arr[i]);
} else {
flatten(arr[i])
}
}
return result;
}
}
Test results: https://codepen.io/ashermike/pen/mKZrWK
It's better to do it in a recursive way, so if still another array inside the other array, can be filtered easily...
const flattenArray = arr =>
arr.reduce(
(res, cur) =>
!Array.isArray(cur)
? res.concat(cur)
: res.concat(flattenArray(cur)), []);
And you can call it like:
flattenArray([[["Alireza"], "Dezfoolian"], ["is a"], ["developer"], [[1, [2, 3], ["!"]]]);
and the result isas below:
["Alireza", "Dezfoolian", "is a", "developer", 1, 2, 3, "!"]
Simply using spread operator we can flatten in the following way.
var OriginalArray = [[5, 1], [6], [2], [8]];
var newArray = [];
for (let i = 0; i < OriginalArray.length; i++) {
newArray.push(...OriginalArray[i]);
}
console.log(newArray)
I have just try to solve the problem without using any inbuild function.
var arr = [1, 3, 4, 65, [3, 5, 6, 9, [354, 5, 43, 54, 54, 6, [232, 323, 323]]]];
var result = [];
function getSingleArray(inArr) {
for (var i = 0; i < inArr.length; i++) {
if (typeof inArr[i] == "object") {
getSingleArray(inArr[i]); // Calling Recursively
} else {
result.push(inArr[i]);
}
}
}
getSingleArray(arr);
console.log(result); // [1, 3, 4, 65, 3, 5, 6, 9, 354, 5, 43, 54, 54, 6, 232, 323, 323]
Here is the solution non recursive flatten deep using a stack.
function flatten(input) {
const stack = [...input];
const res = [];
while (stack.length) {
const next = stack.pop();
if (Array.isArray(next)) {
stack.push(...next);
} else {
res.push(next);
}
}
return res.reverse();
}
const arrays = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]];
flatten(arrays);
[1,[2,3],[4,[5,6]]].reduce(function(p, c) {
return p.concat(c instanceof Array ?
c.reduce(arguments.callee, []) :
[c]);
}, []);
if your array only consists out of integers or strings you can use this dirty hack:
var arr = [345,2,[34],2,[524,[5456]],[5456]];
var flat = arr.toString().split(',');
Works, in FF, IE and Chrome didn't test the other browsers yet.
.toString()
function (.toString
will call for me .toString
recursively) which if I recall correctly returned previously "[object Array]"
instead of a recursive arr.join(',')
:) –
Oscan [[1,2],["3,4"]]
it'll end up with: ["1","2","3", "4"]
–
Oscan ["1","2","3,4"]
–
Fiora [1,[2,3], [], 4, [5]].toString().split(',');
will output ["1", "2", "3", "", "4", "5"]
. Assuming we are interested in numbers, one alternative would be: [1,[2,3], [], 4, [5]].toString().split(',').filter((e) => e !== '').map(Number);
. –
Canada To flatten a two-dimensional array in one line:
[[1, 2], [3, 4, 5]].reduce(Function.prototype.apply.bind(Array.prototype.concat))
// => [ 1, 2, 3, 4, 5 ]
[[1, 2], [3, 4, 5], [6, [[7]]]]
. –
Sacrificial const bindable = Function.bind.bind(Function.bind); const applicable = bindable(Function.apply);
and then [[1, 2], [3, 4, 5]].reduce(applicable([].concat));
. –
Carolus There's a much faster way of doing this than using the merge.concat.apply() method listed in the top answer, and by faster I mean more than several orders of magnitude faster. This assumes your environment has access to the ES5 Array methods.
var array2d = [
["foo", "bar"],
["baz", "biz"]
];
merged = array2d.reduce(function(prev, next) {
return prev.concat(next);
});
Here's the jsperf link: http://jsperf.com/2-dimensional-array-merge
concat
is not only slower, it’s asymptotically slower. –
Frau I'm aware that this is hacky, but the must succinct way I know of to flatten an array(of any depth!) of strings(without commas!) is to turn the array into a string and then split the string on commas:
var myArray =[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]];
var myFlatArray = myArray.toString().split(',');
myFlatArray;
// ["$6", "$12", "$25", "$25", "$18", "$22", "$10", "$0", "$15", "$3", "$75", "$5", "$100", "$7", "$3", "$75", "$5"]
This should work on any depth of nested arrays containing only strings and numbers(integers and floating points) with the caveat that numbers will be converted to strings in the process. This can be solved with a little mapping:
var myArray =[[[1,2],[3,4]],[[5,6],[7,8]],[[9,0]]];
var myFlatArray = myArray.toString().split(',').map(function(e) { return parseInt(e); });
myFlatArray;
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
Recursive version that works on all datatypes
/*jshint esversion: 6 */
// nested array for testing
let nestedArray = ["firstlevel", 32, "alsofirst", ["secondlevel", 456,"thirdlevel", ["theinnerinner", 345, {firstName: "Donald", lastName: "Duck"}, "lastinner"]]];
// wrapper function to protect inner variable tempArray from global scope;
function flattenArray(arr) {
let tempArray = [];
function flatten(arr) {
arr.forEach(function(element) {
Array.isArray(element) ? flatten(element) : tempArray.push(element); // ternary check that calls flatten() again if element is an array, hereby making flatten() recursive.
});
}
// calling the inner flatten function, and then returning the temporary array
flatten(arr);
return tempArray;
}
// example usage:
let flatArray = flattenArray(nestedArray);
/**
* flatten an array first level
* @method flatten
* @param array {Array}
* @return {Array} flatten array
*/
function flatten(array) {
return array.reduce((acc, current) => acc.concat(current), []);
}
/**
* flatten an array recursively
* @method flattenDeep
* @param array {Array}
* @return {Array} flatten array
*/
function flattenDeep(array) {
return array.reduce((acc, current) => {
return Array.isArray(current) ? acc.concat(flattenDeep(current)) : acc.concat([current]);
}, []);
}
/**
* flatten an array recursively limited by depth
* @method flattenDepth
* @param array {Array}
* @return {Array} flatten array
*/
function flattenDepth(array, depth) {
if (depth === 0) {
return array;
}
return array.reduce((acc, current) => {
return Array.isArray(current) ? acc.concat(flattenDepth(current, --depth)) : acc.concat([current]);
}, []);
}
return Array.isArray(current) ? acc.concat(current) : acc.concat([current]);
? Why even check for if the item is also an array, if it's just one level :) –
Houphouetboigny [1,2].concat(3)
is same as [1,2].concat([3])
–
Houphouetboigny The following code will flatten deeply nested arrays:
/**
* [Function to flatten deeply nested array]
* @param {[type]} arr [The array to be flattened]
* @param {[type]} flattenedArr [The flattened array]
* @return {[type]} [The flattened array]
*/
function flattenDeepArray(arr, flattenedArr) {
let length = arr.length;
for(let i = 0; i < length; i++) {
if(Array.isArray(arr[i])) {
flattenDeepArray(arr[i], flattenedArr);
} else {
flattenedArr.push(arr[i]);
}
}
return flattenedArr;
}
let arr = [1, 2, [3, 4, 5], [6, 7]];
console.log(arr, '=>', flattenDeepArray(arr, [])); // [ 1, 2, [ 3, 4, 5 ], [ 6, 7 ] ] '=>' [ 1, 2, 3, 4, 5, 6, 7 ]
arr = [1, 2, [3, 4], [5, 6, [7, 8, [9, 10]]]];
console.log(arr, '=>', flattenDeepArray(arr, [])); // [ 1, 2, [ 3, 4 ], [ 5, 6, [ 7, 8, [Object] ] ] ] '=>' [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
You can just keep on using Array.flat() method to achieve this even when array is a lot more nested.
[1,2,3,[2]].flat()
is equivalent to
[1,2,3,[2]].flat(1)
so as your nesting increases you can keep on increasing number.
eg:
[1,[2,[3,[4]]]].flat(3) // [1, 2, 3, 4]
And if you are not sure about level of nesting you can just pass Infinity as parameter
[1,2,3,[2,[3,[3,[34],43],[34]]]].flat(Infinity) //[1, 2, 3, 2, 3, 3, 34, 43, 34]
[['test,test'], ['test']].join().split(',')
gives ['test', 'test', 'test']
instead of ['test,test', 'test']
. –
Pak You can use Ramda JS flatten
var arr = [[1,2], [3], [4,5]];
var flattenedArray = R.flatten(arr);
console.log(flattenedArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
let arr = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]];
arr = arr.reduce((a, b) => a.concat(b)); // flattened
Simple flatten util i've written
const flatten = (arr, result = []) => {
if (!Array.isArray(arr)){
return [...result, arr];
}
arr.forEach((a) => {
result = flatten(a, result)
})
return result
}
console.log(flatten([1,[2,3], [4,[5,6,[7,8]]]])) // [ 1, 2, 3, 4, 5, 6, 7, 8 ]
Define an array of arrays in javascript called foo and flatten that array of arrays into a single array using javascript's array concat builtin method:
const foo = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
console.log({foo});
const bar = [].concat(...foo)
console.log({bar});
Should print:
{ foo:
[ [ '$6' ],
[ '$12' ],
[ '$25' ],
[ '$25' ],
[ '$18' ],
[ '$22' ],
[ '$10' ] ] }
{ bar: [ '$6', '$12', '$25', '$25', '$18', '$22', '$10' ] }
Since ES2019 has introduced flat and flatMap then flat any array can be done like this:
const myArr = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
const myArrFlat= myArr.flat(Infinity);
console.log(myArrFlat); // ["$6", "$12", "$25", ...]
Ref. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
Recursively calling the deepFlatten
function so we can spread the inner array without using any external helper method is the way to go.
const innerArr = ['a', 'b'];
const multiDimArr = [[1, 2], 3, 4, [5, 6, innerArr], 9];
const deepFlatten = (arr) => {
const flatList = [];
arr.forEach(item => {
Array.isArray(item)
? flatList.push(...deepFlatten(item)) // recursive call
: flatList.push(item)
});
return flatList;
}
This solution will work for any depth level (specifying how deep a nested array structure should be) of array.
function flatten(obj) {
var out = [];
function cleanElements(input) {
for (var i in input){
if (input[i]instanceof Array){
cleanElements(input[i]);
}
else {
out.push(input[i]);
}
}
}
cleanElements(obj);
return (out);
}
Use this method to flat two arrays
arr1.concat(...arr2);
Here is my version of it. It allows you to flatten a complicated object which could be used in more scenarios:
Input
var input = {
a: 'asdf',
b: [1,2,3],
c: [[1,2],[3,4]],
d: {subA: [1,2]}
}
Code
The function is like this:
function flatten (input, output) {
if (isArray(input)) {
for(var index = 0, length = input.length; index < length; index++){
flatten(input[index], output);
}
}
else if (isObject(input)) {
for(var item in input){
if(input.hasOwnProperty(item)){
flatten(input[item], output);
}
}
}
else {
return output.push(input);
}
};
function isArray(obj) {
return Array.isArray(obj) || obj.toString() === '[object Array]';
}
function isObject(obj) {
return obj === Object(obj);
}
Usage
var output = []
flatten(input, output);
Output
["asdf", 1, 2, 3, 1, 2, 3, 4, 1, 2]
If you need to support IE8 and, therefore, can't use methods such as reduce or isArray, here is a possible solution. It is a verbose approach to help you to understand the recursive algorithm.
function flattenArray(a){
var aFinal = [];
(function recursiveArray(a){
var i,
iCount = a.length;
if (Object.prototype.toString.call(a) === '[object Array]') {
for (i = 0; i < iCount; i += 1){
recursiveArray(a[i]);
}
} else {
aFinal.push(a);
}
})(a);
return aFinal;
}
var aMyArray = [6,3,4,[12,14,15,[23,24,25,[34,35],27,28],56],3,4];
var result = flattenArray(aMyArray);
console.log(result);
var arrays = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]];
var merged = [].concat.apply([], arrays);
alert(merged);
You can flatten an array of arrays using Array.prototype.reduce()
and Array.prototype.concat()
var data = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]].reduce(function(a, b) {
return a.concat(b);
}, []);
console.log(data);
Related docs: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
I originally thought to use the .reduce
method and recursively call a function to flatten inner arrays, however this can lead to stack overflows when you are working with a deeply nested array of deeply nested arrays. Using concat is also not the best way to go, because each iteration will create a new shallow copy of the array. What we can do instead is this:
const flatten = arr => {
for(let i = 0; i < arr.length;) {
const val = arr[i];
if(Array.isArray(val)) {
arr.splice(i, 1, ...val);
} else {
i ++;
}
}
return arr;
}
We are not creating new arrays via concat and we are not recursively calling any functions.
I have a simple solution without using in a special js function. (like reduce etc)
const input = [[0, 1], [2, 3], [4, 5]]
let flattened=[];
for (let i=0; i<input.length; ++i) {
let current = input[i];
for (let j=0; j<current.length; ++j)
flattened.push(current[j]);
}
Yet another approach using jQuery $.map() function. From jQuery documentation:
The function can return an array of values, which will be flattened into the full array.
var source = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]];
var target = $.map(source, function(value) { return value; }); // ["$6", "$12", "$25", "$25", "$18", "$22", "$10"]
let arr = [1, [2, 3, [4, 5, [6, 7], [8, 9, 10, 11, 12]]]];
function flattenList(nestedArr) {
let newFlattenList = [];
const handleFlat = (array) => {
let count = 0;
while (count < array.length) {
let item = array[count];
if (Array.isArray(item)) {
handleFlat(item);
} else {
newFlattenList.push(item);
}
count++;
}
};
handleFlat(nestedArr);
return newFlattenList;
}`enter code here`
console.log(flattenList(arr));
Simple and handles multiple levels of nested:
// deeply nested array
const myArray = [1, 2, [3, 4, [5, 6, [[[7,8, [[[[[9, 10]]]]]]]]]]] ;
const flatten = (arr) => {
for (let index = 0; index < arr.length; index++) {
const elem = arr[index];
if (Array.isArray(elem)) {
arr.splice(index, 1, ...elem);
index--;
}
}
};
flatten(myArray);
console.log(myArray); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let mainArr =[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
let temp = [];
const flattenArray = (arr) =>{
let n = arr.length;
for(let i=0;i<n;i++){
if(typeof(arr[i]) == "string" || typeof(arr[i]) == "number"){
temp.push(arr[i]);
}
else if(typeof(arr[i]) == "object"){
flattenArray(arr[i]);
}
}
}
flattenArray(mainArr)
console.log(temp)
Flatten polyfill using recursion:
function flatten(arr) {
let ans = [];
const convert = (arr) => {
if (!Array.isArray(arr)) {
ans.push(arr);
return;
}
arr.forEach((it) => {
convert(it)
});
};
convert(arr);
return ans;
}
console.log(flatten([ [ 1, 2 ], [ 3, [ 4 ] ] ]));
Array.prototype.flatten = Array.prototype.flatten || function() {
return [].reduce.call(this, function(flat, toFlatten) {
return flat.concat(Array.isArray(toFlatten) ? toFlatten.flatten() : toFlatten);
},[])
};
I answer this question just with ES6
, assume the deep array is:
const deepArray = ['1',[['a'],['b']],[2],[[[['4',[3,'c']]]],[5]]];
If you know or guess the depth of your arrays is not more than a number like 7
, use below code:
const flatArray = deepArray.flat(7);
But if you don't know the depth of your deep arrays or your JavaScript
engine doesn't support flat
like react-native
JavaScriptCore
, use below function that is used JavaScript
reduce
function:
const deepFlatten = arr =>
arr.reduce(
(acc, val) =>
Array.isArray(val)
? acc.concat(deepFlatten(val))
: acc.concat(val),
[]
);
Both of methods return below result:
["1", "a", "b", 2, "4", 3, "c", 5]
Much simpler and straight-forward one; with option to deep flatten;
const flatReduce = (arr, deep) => {
return arr.reduce((acc, cur) => {
return acc.concat(Array.isArray(cur) && deep ? flatReduce(cur, deep) : cur);
}, []);
};
console.log(flatReduce([1, 2, [3], [4, [5]]], false)); // => 1,2,3,4,[5]
console.log(flatReduce([1, 2, [3], [4, [5, [6, 7, 8]]]], true)); // => 1,2,3,4,5,6,7,8
const arr = [1, 2, '22',[1,33,44,['ddd'], 5678], 'abbb', 'ccc', 1234];
const flat = String(arr).split(',').map((elm)=> {
return !isNaN(elm) ? Number(elm) : elm
})
console.log(flat)
[23, [34, 454], 12, 34].flatten();
// --> [23,34, 454, 12, 34]
[23, [34, 454,[66,55]], 12, 34].flatten();
// --> [23, 34, 454, [66,55], 12, 34]
[23, [34, 454,[66,55]], 12, 34].flatten(true);
// --> [23, 34, 454, 66, 55, 12, 34]
If all array elements are Integer,Float,... or/and String , So just , do this trick :
var myarr=[1,[7,[9.2]],[3],90];
eval('myarr=['+myarr.toString()+']');
print(myarr);
// [1, 7, 9.2, 3, 90]
I believe that the best way to do this would be something like this:
var flatten = function () {
return [].slice.call(arguments).toString().split(',');
};
I was just looking for the faster and easy solution to do this, why? because I get this as a one interview question and I got curious, so I made this:
function flattenArrayOfArrays(a, r){
if(!r){ r = []}
for(var i=0; i<a.length; i++){
if(a[i].constructor == Array){
flattenArrayOfArrays(a[i], r);
}else{
r.push(a[i]);
}
}
return r;
}
var i = [[1,2,[3]],4,[2,3,4,[4,[5]]]], output;
// Start timing now
console.time("flatten");
output = new Array(JSON.stringify(i).replace(/[^\w\s,]/g,""));
output
// ... and stop.
console.timeEnd("flatten");
// Start timing now
console.time("flatten2");
output = [].concat.apply([], i)
output
// ... and stop.
console.timeEnd("flatten2");
// Start timing now
console.time("flatten3");
output = flattenArrayOfArrays(i)
output
// ... and stop.
console.timeEnd("flatten3");
I used the most popular answers here and my solution. I guess somebody will find this interesting. Cheers!
Sheer Magic of ES6
const flat = A => A.reduce((A, a) => Array.isArray(a) ? [...A, ...flat(a)] : [...A, a], []);
Using code from there.
I would write:
myArray.enumerable().selectMany(function(x) { return x; }).array()
© 2022 - 2025 — McMap. All rights reserved.
reduce
+concat
are O((N^2)/2) where as a accepted answer (just one call toconcat
) would be at most O(N*2) on a bad browser and O(N) on a good one. Also Denys solution is optimized for the actual question and upto 2x faster than the singleconcat
. For thereduce
folks it's fun to feel cool writing tiny code but for example if the array had 1000 one element subarrays all the reduce+concat solutions would be doing 500500 operations where as the single concat or simple loop would do 1000 operations. – Playactingarray.flat(Infinity)
whereInfinity
is the maximum depth to flatten. – Eagle