【问题标题】:JavaScript flattening an array of arrays of objectsJavaScript 展平对象数组
【发布时间】:2015-05-23 09:38:15
【问题描述】:

我有一个包含几个数组的数组,每个数组包含几个对象,类似于这个。

[[object1, object2],[object1],[object1,object2,object3]]

这是记录到控制台的对象的屏幕截图。

将其展平为对象数组的最佳方法是什么?

我试过这个没有运气:

console.log(searchData);  
  var m = [].concat.apply([],searchData);    
console.log(m);

searchData 注销了上面的截图,但是 m 注销了 [ ]

这里是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}]]

【问题讨论】:

  • 我喜欢arr.reduce(function(a,b){return a.concat(b);});
  • 出于某种原因,这给了我一个空的 [ ]。我尝试过的其他几种方法也有...我不知道为什么?
  • 如果提供的所有选项都不起作用,那你就做错了。
  • 你能把searchData的内容也发一下吗?

标签: javascript arrays loops flatten


【解决方案1】:

你可以像下面这样使用Array.concat:-

var arr = [['object1', 'object2'],['object1'],['object1','object2','object3']];
var flattened = [].concat.apply([],arr);

flattened 将是您预期的数组。

ES 2020 提供 flat,如果您想迭代,还提供 flatMap 到平面列表:

[['object1'], ['object2']].flat() // ['object1', 'object2']

【讨论】:

  • 由于某种原因,这会返回一个空数组。任何想法为什么会发生这种情况?
  • 我比我的减少答案更喜欢这个。
  • 它适用于答案中提供的数组。出于某种原因,我的数组虽然返回 [ ]。
  • @byrdr 你能发布你到底在尝试什么吗?
  • @Mritunjay 你能在你的代码中添加解释吗?
【解决方案2】:

如果您只需要简单的展平,这可能有效:

var arr = [['object1', 'object2'],['object1'],['object1','object2','object3']];
var flatenned = arr.reduce(function(a,b){ return a.concat(b) }, []);

对于更复杂的展平,Lodash 有展平功能,这可能是你需要的: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];

【讨论】:

  • 展示为什么更喜欢 [].reduce 与 _.flatten 的好例子!
  • @dandavis 好吧,他需要做的就是指定_.flatten 的可选参数以获取深层行为,或者调用_.flattenDeep
【解决方案3】:

递归地展平一个数组:

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

【讨论】:

  • 成功了!谢谢,我将不得不剖析代码。那么为什么其他的都没有,而这个却可以工作呢?
  • 关于两次检查数组的模糊不清的东西。
  • @byrdr:除非您歪曲数据,否则其他答案都可以正常工作。
  • @byrdr:您有几个解决方案已被验证为有效,但您报告了同样的问题。这应该告诉您问题出在其他地方。这些数据是否来自 XHR 请求?如果是这样,您是否在记录数据之前不等待响应?
  • @byrdr:不值得猜测何时可以提供正在运行的实际代码和正在执行的日志记录。
【解决方案4】:

深度(嵌套)展平的递归解决方案:

function flatten(a) {
  return Array.isArray(a) ? [].concat.apply([], a.map(flatten)) : a;
}

使用 ES6 更紧凑:

var flatten = a => Array.isArray(a) ? [].concat(...a.map(flatten)) : a;

为了好玩,使用名为 F 的生成器“flatten”,懒惰地生成扁平值:

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 ]

对于那些不熟悉生成器的人,yield * 语法从另一个生成器生成值。 Array.from 接受一个迭代器(例如调用生成器函数的结果)并将其转换为一个数组。

【讨论】:

    【解决方案5】:
    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
    

    【讨论】:

    • 这个答案是ECMAScript 2015,它没有被javascript标签覆盖,除非适当的标签被附加到这个问题的标签列表中,否则需要一个传统的JavaScript答案。
    【解决方案6】:

    使用 ES6 扩展运算符

    Array.prototype.concat(...searchData)

    [].concat(...searchData)

    【讨论】:

      【解决方案7】:

      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]

      【讨论】:

        【解决方案8】:
        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]);
        }
        }
        }
        

        调用函数

        flatten(arr);
        console.log(res);
        

        结果

        [1, 9, 22, 3]
        

        【讨论】:

          【解决方案9】:

          我注意到人们正在使用成本不友好的递归,尤其是新的 ES6 标准赋予了我们传播运算符的力量。当您将项目推入主阵列时,只需使用 ... 它会自动添加展平对象。类似的东西

          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]
          

          【讨论】:

            【解决方案10】:

            你可以使用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);

            在你的情况下:

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

            【讨论】:

              【解决方案11】:

              我将对象数组展平并返回单个数组的解决方案。

              flattenArrayOfObject = (arr) => {
                const flattened = {};
              
                arr.forEach((obj) => {
                  Object.keys(obj).forEach((key) => {
                    flattened[key] = obj[key];
                  });
                });
              
                return flattened;
              };
              

              例子

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

              【讨论】:

                【解决方案12】:

                如果每个对象都有一个数组并以同样的方式继续嵌套:

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

                我的数据是这样的:

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

                ]

                【讨论】:

                  【解决方案13】:

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

                  【讨论】:

                    猜你喜欢
                    • 2018-02-24
                    • 2023-01-11
                    • 1970-01-01
                    • 2020-07-19
                    • 2021-12-25
                    • 2023-03-20
                    • 1970-01-01
                    • 2018-07-09
                    • 2020-07-11
                    相关资源
                    最近更新 更多