【问题标题】:lodash: combine array of objectslodash:组合对象数组
【发布时间】:2017-02-22 11:05:17
【问题描述】:

在 lodash 中,我想将对象数组转换为包含每个属性数组的单个对象。

我有一个对象数组:

var students = [{
    name: 'A',
    idNo: 1,
    marks: {
        math: 98,
        sci: 97,
        eng: 89
    }
}, {
    name: 'B',
    idNo: 2,
    marks: {
        math: 88,
        sci: 87,
        eng: 79
    }
}, {
    name: 'C',
    idNo: 3,
    marks: {
        math: 87,
        sci: 98,
        eng: 91
    }
}]

我想像这样组合/重塑它们:

{
    name: [A, B, C],
    idNo: [1, 2, 3],
    marks: [{
            math: 98,
            sci: 97,
            eng: 89
        }, {

            math: 88,
            sci: 87,
            eng: 79            
    }, {
            math: 87,
            sci: 98,
            eng: 91
        }
    }]
}

我希望这完全使用 lodash 或 js 内置函数来完成,没有任何循环。

编辑:我已经按照 Nenad 的建议实施了一个解决方案。我想要一个 lodash 中的实用函数。

【问题讨论】:

    标签: javascript arrays functional-programming lodash


    【解决方案1】:

    你可以使用 lodash 的 mapValues 函数:

    var result = _.mapValues(students[0], (value, key) => _.map(students, key));
    

    mapValues 创建一个与作为第一个参数传递给它的对象具有相同键的对象。这里我们传递了学生数组students[0] 中的第一个对象,所以mapValues 返回的对象看起来像这样:

    {
        name: ....,
        idNo: ....,
        marks: ....
    }
    

    每个键的值由作为第二个参数传递给mapValues 的函数确定。 mapValues 将为每个键调用此函数并传递值和键。我们对值不感兴趣,但键用于为该键提取 student 数组中的所有值(通过调用 map 并将键作为第二个参数)。

    var students = [{
        name: 'A',
        idNo: 1,
        marks: {
            math: 98,
            sci: 97,
            eng: 89
        }
    }, {
        name: 'B',
        idNo: 2,
        marks: {
            math: 88,
            sci: 87,
            eng: 79
        }
    }, {
        name: 'C',
        idNo: 3,
        marks: {
            math: 87,
            sci: 98,
            eng: 91
        }
    }]
    
    
    var result = _.mapValues(students[0], (value, key) => _.map(students, key));
    
    document.getElementById('result').textContent = JSON.stringify(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
    
    <p>
      <pre id="result"></pre>
    </p>

    【讨论】:

      【解决方案2】:

      您可以使用 _.mergeWith() 和扩展运算符将数组中的所有对象合并为一个新对象:

      const students = [{"name":"A","idNo":1,"marks":{"math":98,"sci":97,"eng":89}},{"name":"B","idNo":2,"marks":{"math":88,"sci":87,"eng":79}},{"name":"C","idNo":3,"marks":{"math":87,"sci":98,"eng":91}}];
      
      const result = _.mergeWith({}, ...students, (objValue, srcValue) => 
        (objValue || []).concat(srcValue));
      
      console.log(result);
      &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"&gt;&lt;/script&gt;

      在旧版浏览器中,您可以将所有参数连接到一个数组中,并使用_.spread()

      var students = [{"name":"A","idNo":1,"marks":{"math":98,"sci":97,"eng":89}},{"name":"B","idNo":2,"marks":{"math":88,"sci":87,"eng":79}},{"name":"C","idNo":3,"marks":{"math":87,"sci":98,"eng":91}}];
                                                
      var result = _.spread(_.mergeWith)([{}].concat(students, function(objValue, srcValue){
        return (objValue || []).concat(srcValue);
      }));
      
      console.log(result);
      &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"&gt;&lt;/script&gt;

      【讨论】:

        【解决方案3】:

        您可以使用reduce()forEach() 来获得想要的结果。

        var students = [{"name":"A","idNo":1,"marks":{"math":98,"sci":97,"eng":89}},{"name":"B","idNo":2,"marks":{"math":88,"sci":87,"eng":79}},{"name":"C","idNo":3,"marks":{"math":87,"sci":98,"eng":91}}];
        
        var result = students.reduce(function(r, e) {
          Object.keys(e).forEach(function(k) {
            if (!r[k]) {
              r[k] = [];
            }
            r[k].push(e[k])
          })
          return r;
        }, {})
        
        console.log(result)

        【讨论】:

        • 我应该提到这个,但我已经用过这个了。我想知道 lodash 是否为此提供了内置功能。
        【解决方案4】:

        你可以用一个 reduce 来做到这一点;

        var students = [{
            name: 'A',
            idNo: 1,
            marks: {
                math: 98,
                sci: 97,
                eng: 89
            }
        }, {
            name: 'B',
            idNo: 2,
            marks: {
                math: 88,
                sci: 87,
                eng: 79
            }
        }, {
            name: 'C',
            idNo: 3,
            marks: {
                math: 87,
                sci: 98,
                eng: 91
            }
        }],
             result = students.reduce((p,c) => (p.name.push(c.name), p.idNo.push(c.idNo), p.marks.push(c.marks), p), {name:[], idNo:[], marks:[]});
        console.log(result);

        【讨论】:

          【解决方案5】:

          _.mergeWith 的另一个 lodash 示例

          var students = [{ name: 'A', idNo: 1, marks: { math: 98, sci: 97, eng: 89 } }, { name: 'B', idNo: 2, marks: { math: 88, sci: 87, eng: 79 } }, { name: 'C', idNo: 3, marks: { math: 87, sci: 98, eng: 91 } }],
              result = {};
          
              _.forEach(students, v => _.mergeWith(result, v, (o, s) => !_.isArray(o) ? [s] : o.concat(s)));
          
          console.log(result);
          &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"&gt;&lt;/script&gt;

          【讨论】:

            【解决方案6】:

            .reduce(collection, [iteratee=.identity], [accumulator]) 的另一个 lodash 示例。

            • collection (Array|Object):要迭代的集合。
            • [iteratee=_.identity] (Function):每次迭代调用的函数。
            • [accumulator] (*):初始值。

            代码:

            var students = [{name: 'A', idNo: 1, marks: { math: 98, sci: 97, eng: 89}}, {name: 'B', idNo: 2, marks: { math:88,  sci: 87,  eng: 79}}, {name: 'C', idNo: 3, marks: { math: 87, sci: 98, eng: 91}}],
                obj = _.reduce(students, function(o, item) {
                  o.name.push(item.name);
                  o.idNo.push(item.idNo);
                  o.marks.push(item.marks);
                  return o;
                }, {name: [], idNo: [], marks: []});
            
            console.log(obj);
            &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"&gt;&lt;/script&gt;

            【讨论】:

              猜你喜欢
              • 2015-06-01
              • 1970-01-01
              • 2016-06-12
              • 1970-01-01
              • 1970-01-01
              • 2015-09-04
              • 1970-01-01
              • 2019-05-07
              • 2015-07-07
              相关资源
              最近更新 更多