56

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}]]
cweiske
  • 30,033
  • 14
  • 133
  • 194
byrdr
  • 5,197
  • 12
  • 48
  • 78
  • 11
    i like `arr.reduce(function(a,b){return a.concat(b);});` – dandavis Mar 20 '15 at 03:09
  • 1
    for some reason that gives me an empty [ ]. Several other methods I've tried also have...I'm not sure why? – byrdr Mar 20 '15 at 03:13
  • 2
    you're doing something else wrong if all the options presented are not working. – dandavis Mar 20 '15 at 03:16
  • can you just post the content of searchData as well ? – Mritunjay Mar 20 '15 at 03:21
  • Works: http://jsfiddle.net/m415vttv/ – Lye Fish Mar 20 '15 at 03:27
  • Possible duplicate of [Merge/flatten an array of arrays in JavaScript?](http://stackoverflow.com/questions/10865025/merge-flatten-an-array-of-arrays-in-javascript) – Nakilon Mar 09 '17 at 18:35
  • To flatten deeply nested array of objects you need recursion. Check [this post](https://www.techighness.com/post/javascript-flatten-deeply-nested-array-of-objects-into-single-level-array/) for a solution. – Talha Awan Aug 31 '21 at 06:38

14 Answers14

85

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']
Léa Gris
  • 17,497
  • 4
  • 32
  • 41
Mritunjay
  • 25,338
  • 7
  • 55
  • 68
  • 2
    For some reason this returns an empty array. Any ideas why that might be occuring? – byrdr Mar 20 '15 at 03:15
  • i like this better even than my reduce answer. – dandavis Mar 20 '15 at 03:16
  • 1
    It works on the array provided in the answer. For some reason my array returns [ ] though. – byrdr Mar 20 '15 at 03:17
  • @byrdr can you post what exactly you are trying? – Mritunjay Mar 20 '15 at 03:18
  • 2
    @Mritunjay can you please add explanation to your code? – Nishanth Matha Mar 20 '15 at 04:26
  • @NishanthMatha the trick is that .apply() takes the arguments as an array see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply – wutzebaer Aug 16 '18 at 20:19
  • Neither approach works for me. I use `json_files.map((json_file: File) => { json_file.text().then(value => a_nested_array.push(JSON.parse(value))) });` to create the array and wanted to do `a_nested_array.flat()` ... but the nested arrays are not flattened – c0mr4t Feb 08 '22 at 15:57
18

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.

11

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];
Huy Hoang Pham
  • 4,107
  • 1
  • 16
  • 28
  • good example for showing why to prefer [].reduce vs _.flatten ! – dandavis Mar 20 '15 at 03:19
  • @dandavis Well, all he needs to do is specify the optional argument to `_.flatten` to get the deep behavior, or call `_.flattenDeep`. –  Mar 20 '15 at 04:43
5

Using ES6 Spread Operator

Array.prototype.concat(...searchData)

OR

[].concat(...searchData)

Shreyas
  • 1,927
  • 17
  • 34
5

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);
Taki
  • 17,320
  • 4
  • 26
  • 47
3

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]
2

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('<pre>' + JSON.stringify(data, null, 2) + '</pre><hr>');
}
* {font-size: 12px; }
Miguel Mota
  • 20,135
  • 5
  • 45
  • 64
2
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
Alexander Abashkin
  • 1,187
  • 4
  • 13
  • 18
  • 1
    This answer is ECMAScript 2015 which is not covered by the [tag:javascript] tag, unless the appropriate tag has been appended to the tag list of this question, a traditional JavaScript answer is expected. –  Aug 02 '15 at 00:04
2

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]
Adnan Khan
  • 387
  • 2
  • 12
2

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' }
// }
thodwris
  • 1,327
  • 1
  • 17
  • 27
U.A
  • 2,991
  • 3
  • 24
  • 36
1

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": []
        }
    ]
}

]

0

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]
0
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]
Gajender Singh
  • 1,285
  • 14
  • 13
0

// 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'
Rohit
  • 7
  • 2