【问题标题】:how do I create an array of objects with array in the object from an object with the same key in javascript如何从 javascript 中具有相同键的对象创建对象中包含数组的对象数组
【发布时间】:2016-01-30 22:23:08
【问题描述】:

我有一个看起来像这样的对象数组

[{
        "name": "Agile Process",
        "id": 27,
        "score": 3,
        "source": "Self"
    },{
        "name": "Agile Process",
        "id": 27,
        "score": 4,
        "source": "Trainer"
    },{
        "name": "2 & 3 Tier Architecture",
        "id": 37,
        "score": 4,
        "source": "Self"
    },{
        "name": "2 & 3 Tier Architecture",
        "id": 37,
        "score": 5,
        "source": "Trainer"
 }]

我希望能够制作这样的东西,我一直在努力,但我似乎没有掌握它。

[
    {
        "name": "Agile Process",
        "id": 7,
        "data": [
            {
                "score": 3,
                "source": "Self"
            },{
                "score": 4,
                "source": "Trainer"
            }
        ]
    },
    {
        "name": "2 & 3 Tier Architecture",
         "id": 37,
         "data": [
            {
                "score": 4,
                "source": "Self"
            },{
                "score": 5,
                "source": "Trainer"
            }]
        }
  ];

我该如何解决这个问题?

【问题讨论】:

    标签: javascript arrays node.js underscore.js lodash


    【解决方案1】:

    这是一个纯 javascript 解决方案:在初始数组上使用 reduce 方法,使用结果数组(起初为空)作为累加器,它将存储转换后的数据。当 reduce 方法遍历初始数组的项目时,检查结果数组是否包含具有当前项目 id 的元素。如果是这样,那么只需向其中添加新数据,否则在结果数组中创建一个新项目。

    var data = [{
            "name": "Agile Process",
            "id": 27,
            "score": 3,
            "source": "Self"
        },{
            "name": "Agile Process",
            "id": 27,
            "score": 4,
            "source": "Trainer"
        },{
            "name": "2 & 3 Tier Architecture",
            "id": 37,
            "score": 4,
            "source": "Self"
        },{
            "name": "2 & 3 Tier Architecture",
            "id": 37,
            "score": 5,
            "source": "Trainer"
     }];
    
    
    
    var newData = [];
    
    newData = data.reduce(function(acc, current) {
      var existingArr = acc.filter(function(x) { return x.id === current.id });
      if(existingArr.length === 0) {
        acc.push({ name: current.name, id: current.id, data: [{ score: current.score, source: current.source }] });
      }
      else {
        existingArr[0].data.push({ score: current.score, source: current.source });
      }
      return acc;
    }, newData);
    

    【讨论】:

    • 谢谢@all...我会用这个解决方案...原因可以找到here
    • 仍然可以改进:jsperf.com/group-object-with-same-key/2 运行过滤器功能总是会降低性能,尤其是在原始数组包含许多对象的情况下。我的解决方案缓存了 id,使其更快。
    【解决方案2】:

    一种可能的方法:

    _.values(_.reduce(arr, function(acc, el) {
      var id = el.id;
      if (!acc.hasOwnProperty(id)) {
        acc[id] = _.pick(el, 'id', 'name');
        acc[id].data = [];
      }
      acc[id].data.push(_.pick(el, 'score', 'source'));
      return acc;
    }, {}));
    

    Demo。当您需要分组时,这是一种常用的方法。

    【讨论】:

    • 这真是火箭科学+1
    【解决方案3】:

    此版本使用groupBy 按 id 对项目进行分组,然后映射到每个分组以创建所需的对象:

    var groupToItem = function(items){
        return {
            id: items[0].id,
            name: items[0].name,
            data: _.map(items, function(item){
                return _.pick(item, 'score', 'source');
            })
        }
     }
    
     var result = _.chain(data)
        .groupBy('id')
        .map(groupToItem)
        .value();
    

    【讨论】:

      【解决方案4】:

      纯 Javascript 解决方案,但仅适用于您的特定数据结构:

      function groupObjectsById(array){
          var output = [];
          var ids = [];
          for(var i = 0; i < array.length; i++){
              var current = array[i];
              if(ids.indexOf(current.id) > -1){
                  var objInOutput = output.filter(function(obj){
                      if(obj.id === current.id){
                          return obj;
                      }
                  })[0];
                  var dataObj = { score: current.score, source: current.source};
                  objInOutput.data.push(dataObj);
              }else{
                  var outputObject = {name: current.name, id: current.id};
                  outputObject.data = [{ score: current.score, source: current.source}];          
                  output.push(outputObject);
                  ids.push(current.id);
              }
          }
          return output;
      }
      

      【讨论】:

        猜你喜欢
        • 2022-11-11
        • 2015-03-05
        • 2018-12-30
        • 2019-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多