I am trying to flatten an array but I'm having difficulties.
My code:
var arr = [["2"],["3", "4"], "5", [["6"], ["7"]] ];
var res = [].concat.apply([], arr);
//Using reduce(ES5)
function test(args){
var sum = args.reduce(function(acc, val){
acc.concat(Array.isArray(val)? test(val): val);
});
}
//Regular implementation
function test2(arr){
var result = [];
arr.forEach(function(val){
if(Array.isArray(val)){
result = [].concat.apply([], val);
} else {
result.concat(val);
}
});
return result;
}
console.log(test(arr));
console.log(test2(arr));
Expected Output:
["2", "3", "4","5", "6", "7"]
Can someone enlighten me where I'm going wrong?
4 Answers 4
Thats it. So simple
var arr = [["2"], ["3", "4"], "5", [["6"], ["7"]]];
function test2(arr) {
return arr.toString().split(",");
}
console.log(test2(arr));
3 Comments
[{foo: 1}, [{age: 2}, {foo: 3}]] or ['a string, has commas']Since its a nested structure, you should use recursion
Logic
- Loop over passed array and check if current item is an array.
- If yes, repeat the process.
- If not, push value to temp array.
- Merge return value of each recursion to previous one.
Array.forEach
var arr = [["2"],["3", "4"], "5", [["6"], ["7"]] ];
function getFlattenArray(array){
var _tmp = [];
array.forEach(function(item){
if(Array.isArray(item)) {
_tmp = _tmp.concat(getFlattenArray(item))
}
else{
_tmp.push(item);
}
})
return _tmp;
}
var result = getFlattenArray(arr);
console.log(result)
Array.reduce
var arr = [["2"],["3", "4"], "5", [["6"], ["7"]] ];
function getFlattenArray(array){
return array.reduce(function(p,c){
if(Array.isArray(c)) {
p = p.concat(getFlattenArray(c))
}
else{
p.push(c);
}
return p
}, [])
}
var result = getFlattenArray(arr);
console.log(result)
ES6 Version
var arr = [["2"],["3", "4"], "5", [["6"], ["7"]] ];
function getFlattenArray(array){
return array.reduce((p,c) => (Array.isArray(c) ? p=p.concat(getFlattenArray(c)) : p.push(c) ) && p, [])
}
var result = getFlattenArray(arr);
console.log(result)
1 Comment
I think the reason the code I linked you wasn't working was that you probably made the same error I did. I believe (don't really care to look it up, someone will correct me if I am wrong) that arrow functions automatically return the last line, so when turning the code into ES5 you forget to return the arr.reduce(...).
This works for me, Chrome on Windows.
var arr = [
["2"],
["3", "4"], "5", [
["6"],
["7"]
]
];
function flatten(arr) {
return arr.reduce(function(acc, val) {
return acc.concat(Array.isArray(val) ? flatten(val) : val);
}, []);
}
console.log(flatten(arr));
Comments
var arr = [["2"],["3", "4"], "5", [["6"], ["7"]] ];
var flatten = arr.flat(Infinity);
console.log(flatten);
Since Array.prototype.flat() has been included in the standard ECMAScript 2019 (ES10), there is no need to implement your own methods to flatten arrays.
The flat method can take a parameter to specify how deep a nested array structure should be flattened. In the above example I'm passing the global scope variable Infinity so it flattens all the levels.
At the time of writing (04/11/2019) all major browsers except Edge have implemented the feature in their newer versions. Babel 7.4.0 (with core-js@3) also comes with it.
[[[]], [[]]]and not[[],[],[]]flatten([[[1, [1.1]], 2, 3], [4, 5]]); // [1, 1.1, 2, 3, 4, 5]