JavaScript flattening an array of arrays of objects
JavascriptArraysLoopsFlattenJavascript Problem Overview
I have an array which contains several arrays, each containing several objects, similar to this.
[[object1, object2],[object1],[object1,object2,object3]]
Here is a screenhot of the object logged to the console.
What would be the best approach to flattening this out so it just an array of objects?
I've tried this with no luck:
console.log(searchData);
var m = [].concat.apply([],searchData);
console.log(m);
searchData logs out the screenshot above, but m logs out [ ]
Here is the actual contents of searchData:
[[{"_id":"55064111d06b96d974937a6f","title":"Generic Title","shortname":"generic-title","contents":"<p>The Healing Center offers practical, social, and spiritual support to individuals and families. Services include, but are not limited to: food and clothing, job skills training and job search assistance, auto repair (Saturdays only), mentoring, financial counseling, tutoring, prayer, life skills training, and helpful information about local community services.</p><p>Stay in touch with us:</p>","__v":0},{"_id":"5508e1405c621d4aad2d2969","title":"test english","shortname":"test-page","contents":"<h2>English Test</h2>","__v":0}],[{"_id":"550b336f33a326aaee84f883","shortname":"ok-url","title":"now english","contents":"<p>okokko</p>","category":"Transportation","__v":0}]]
Javascript Solutions
Solution 1 - Javascript
You can use Array.concat like bellow:-
var arr = [['object1', 'object2'],['object1'],['object1','object2','object3']];
var flattened = [].concat.apply([],arr);
flattened
will be your expected array.
ES 2020 gives the flat, also flatMap if you want to iterate over, to flat lists of lists:
[['object1'], ['object2']].flat() // ['object1', 'object2']
Solution 2 - Javascript
A recursive solution for deep (nested) flattening:
function flatten(a) {
return Array.isArray(a) ? [].concat.apply([], a.map(flatten)) : a;
}
A bit more compactly with ES6:
var flatten = a => Array.isArray(a) ? [].concat(...a.map(flatten)) : a;
For fun, using a generator named F
for "flatten", to lazily generate flattened values:
function *F(a) {
if (Array.isArray(a)) for (var e of a) yield *F(e); else yield a;
}
>> console.log(Array.from(F([1, [2], 3])));
<< [ 1, 2, 3 ]
For those not familiar with generators the yield *
syntax yields values from another generator. Array.from
takes an iterator (such as results from invoking the generator function) and turns it into an array.
Solution 3 - Javascript
If you only need simple flatten, this may works:
var arr = [['object1', 'object2'],['object1'],['object1','object2','object3']];
var flatenned = arr.reduce(function(a,b){ return a.concat(b) }, []);
For more complex flattening, Lodash has the flatten function, which maybe what you need: https://lodash.com/docs#flatten
//Syntax: _.flatten(array, [isDeep])
_.flatten([1, [2, 3, [4]]]);
// → [1, 2, 3, [4]];
// using `isDeep` to recursive flatten
_.flatten([1, [2, 3, [4]]], true);
// → [1, 2, 3, 4];
Solution 4 - Javascript
> Using ES6 Spread Operator
Array.prototype.concat(...searchData)
OR
[].concat(...searchData)
Solution 5 - Javascript
you can use flat() :
const data = [ [{id:1}, {id:2}], [{id:3}] ];
const result = data.flat();
console.log(result);
// you can specify the depth
const data2 = [ [ [ {id:1} ], {id:2}], [{id:3}] ];
const result2 = data2.flat(2);
console.log(result2);
in your case :
const data = [[{"_id":"55064111d06b96d974937a6f","title":"Generic Title","shortname":"generic-title","contents":"<p>The Healing Center offers practical, social, and spiritual support to individuals and families. Services include, but are not limited to: food and clothing, job skills training and job search assistance, auto repair (Saturdays only), mentoring, financial counseling, tutoring, prayer, life skills training, and helpful information about local community services.</p><p>Stay in touch with us:</p>","__v":0},{"_id":"5508e1405c621d4aad2d2969","title":"test english","shortname":"test-page","contents":"<h2>English Test</h2>","__v":0}],[{"_id":"550b336f33a326aaee84f883","shortname":"ok-url","title":"now english","contents":"<p>okokko</p>","category":"Transportation","__v":0}]]
const result = data.flat();
console.log(result);
Solution 6 - Javascript
I've noticed that people are using recursions which are not cost friendly, especially with new ES6 standards giving us the power of spread operators. When you're pushing the items into the master array just use ... and it will automatically add flattened objects. Something like
array.push(...subarray1) // subarray1 = [object1, object2]
array.push(...subarray2) // subarray2 = [object3]
array.push(...subarray3) // subarray3 = [object4,object5, object6]
// output -> array = [object1, object2, object3, object4, object5, object6]
Solution 7 - Javascript
Recursively flatten an array:
function flatten(array) {
return !Array.isArray(array) ? array : [].concat.apply([], array.map(flatten));
}
var yourFlattenedArray = flatten([[{"_id":"55064111d06b96d974937a6f","title":"Generic Title","shortname":"generic-title","contents":"<p>The Healing Center offers practical, social, and spiritual support to individuals and families. Services include, but are not limited to: food and clothing, job skills training and job search assistance, auto repair (Saturdays only), mentoring, financial counseling, tutoring, prayer, life skills training, and helpful information about local community services.</p><p>Stay in touch with us:</p>","__v":0},{"_id":"5508e1405c621d4aad2d2969","title":"test english","shortname":"test-page","contents":"<h2>English Test</h2>","__v":0}],[{"_id":"550b336f33a326aaee84f883","shortname":"ok-url","title":"now english","contents":"<p>okokko</p>","category":"Transportation","__v":0}]]
);
log(yourFlattenedArray);
function log(data) { document.write('
' + JSON.stringify(data, null, 2) + '
'); }
- {font-size: 12px; }
Solution 8 - Javascript
let functional = {
flatten (array) {
if (Array.isArray(array)) {
return Array.prototype.concat(...array.map(this.flatten, this));
}
return array;
}
};
functional.flatten([0, [1, 2], [[3, [4]]]]); // 0, 1, 2, 3, 4
Solution 9 - Javascript
My solution to flatten an array of objects and return a single array.
flattenArrayOfObject = (arr) => {
const flattened = {};
arr.forEach((obj) => {
Object.keys(obj).forEach((key) => {
flattened[key] = obj[key];
});
});
return flattened;
};
Example
const arr = [ { verify: { '0': 'xyzNot verified', '1': 'xyzVerified' }, role_id: { '1': 'xyzMember', '2': 'xyzAdmin' }, two_factor_authentication: { '0': 'No', '1': 'Yes' } }, { status: { '0': 'xyzInactive', '1': 'Active', '2': 'xyzSuspend' } }]
flattenArrayOfObject(arr)
// {
// verify: { '0': 'xyzNot verified', '1': 'xyzVerified' },
// status: { '0': 'xyzInactive', '1': 'Active', '2': 'xyzSuspend' },
// role_id: { '1': 'xyzMember', '2': 'xyzAdmin' },
// two_factor_authentication: { '0': 'No', '1': 'Yes' }
// }
Solution 10 - Javascript
You can use this custom recursive method to flattened any nested array
const arr = [
[1, 2],
[3, 4, 5],
[6, [7, 8], 9],
[10, 11, 12]
]
const flatenedArray = arr => {
let result = [];
if(!arr.constructor === Array) return;
arr.forEach(a => {
if(a.constructor === Array) return result.push(...flatenedArray(a));
result.push(a);
});
return result;
}
console.log(flatenedArray(arr)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Solution 11 - Javascript
If each object has an array and continues in the same way nested :
function flatten(i,arrayField){
if(Array.isArray(i)) return i.map(c=>flatten(c,arrayField));
if(i.hasOwnProperty(arrayField)) return [{...i,[arrayField]:null},...i[arrayField].map(c=>flatten(c,arrayField))];
return {...i,[arrayField]:null};
}
let data=flatten(myData,'childs');
mydata like this :
[{ "id": 1, "title": "t1", "sort_order": 200, "childs": [ { "id": 2, "title": "t2", "sort_order": 200, "childs": []
},
{
"id": 3,
"title":"mytitle",
"sort_order": 200,
"childs": []
},
{
"id": 4,
"title":"mytitle",
"sort_order": 200,
"childs": []
},
{
"id": 5,
"title":"mytitle",
"sort_order": 200,
"childs": []
},
{
"id": 6,
"title":"mytitle",
"sort_order": 200,
"childs": []
}
]
},
{
"id": 7,
"title": "راهنما",
"sort_order":"mytitle",
"childs": [
{
"id": 8,
"title":"mytitle",
"sort_order": 200,
"childs": []
},
{
"id": 9,
"title":"mytitle",
"sort_order": 200,
"childs": []
},
{
"id": 10,
"title":"mytitle",
"sort_order": 200,
"childs": []
}
]
}
]
Solution 12 - Javascript
let nestedArray = [[1, 2], [3, 4], [5, 6]];
let flattenArray = function(nestedArray) {
let flattenArr = [];
nestedArray.forEach(function(item) {
flattenArr.push(...item);
});
return flattenArr;
};
console.log(flattenArray(nestedArray)); // [1, 2, 3, 4, 5, 6]
Solution 13 - Javascript
var arr = [1,[9,22],[[3]]];
var res = [];
function flatten(arr){
for(let i=0;i<arr.length;i++){
if(typeof arr[i] == "number"){
res.push(arr[i]);
}
else if(typeof arr[i] == "object"){
fatten(arr[i]);
}
}
}
Calling function
flatten(arr);
console.log(res);
Result
[1, 9, 22, 3]
Solution 14 - Javascript
// Polyfill flat method
var flatten = a => Array.isArray(a) ? [].concat(...a.map(flatten)) : a;
var deepFlatten = (arr, depth = 1) => {
return depth > 0 ? arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? deepFlatten(val, depth - 1) : val), [])
: arr.slice();
}
console.log(deepFlatten([0, 1, 2, [[[3, 4]]]], Infinity));
// You can pass label in place of 'Infinity'