admin管理员组

文章数量:1134247

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

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}]]
Share Improve this question edited May 12, 2017 at 20:12 cweiske 31k15 gold badges146 silver badges205 bronze badges asked Mar 20, 2015 at 3:07 byrdrbyrdr 5,45712 gold badges49 silver badges80 bronze badges 7
  • 11 i like arr.reduce(function(a,b){return a.concat(b);}); – dandavis Commented Mar 20, 2015 at 3:09
  • 1 for some reason that gives me an empty [ ]. Several other methods I've tried also have...I'm not sure why? – byrdr Commented Mar 20, 2015 at 3:13
  • 2 you're doing something else wrong if all the options presented are not working. – dandavis Commented Mar 20, 2015 at 3:16
  • can you just post the content of searchData as well ? – Mritunjay Commented Mar 20, 2015 at 3:21
  • Works: jsfiddle.net/m415vttv – Lye Fish Commented Mar 20, 2015 at 3:27
 |  Show 2 more comments

15 Answers 15

Reset to default 89

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

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.

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

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);

Using ES6 Spread Operator

Array.prototype.concat(...searchData)

OR

[].concat(...searchData)

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]

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; }

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

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]

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' }
// }

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

]

JavaScript flat is a way to achieve a flattened array from a multidimensional array

For two dimentional array

const data = [
  [{id: 1, name: 'Test Name'}], 
  [{id: 2, name: 'Test Name 2'}]
 ].flat()
console.log(data)

For multidimensional array

const data = [
  [{id: 1, name: 'Test Name'}], 
  [
    {id: 2, name: 'Test Name 2'}, 
    [{id: 3, name: 'Test Name 3'}]
  ]
].flat(Infinity)
console.log(data)

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]

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]

// 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'

本文标签: JavaScript flattening an array of arrays of objectsStack Overflow