如何从javascript中具有相同键的对象创建对象数组

如何从javascript中具有相同键的对象创建对象数组,javascript,arrays,node.js,underscore.js,lodash,Javascript,Arrays,Node.js,Underscore.js,Lodash,我有一个像这样的对象数组 [{ "name": "Agile Process", "id": 27, "score": 3, "source": "Self" },{ "name": "Agile Process", "id": 27, "score": 4, "source": "Trainer" },{ "name": "2 &

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

[{
        "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解决方案:在初始数组上使用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);

这里有一个纯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);
一种可能的办法:

_.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;
}, {}));
。当您需要将事情分组时,这是一种常见的方法。

一种可能的方法:

_.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;
}, {}));
。当您需要对项目进行分组时,这是一种常用方法。

此版本用于按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();
此版本使用按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();

纯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;
}
函数组objectsbyid(数组){
var输出=[];
var-id=[];
对于(var i=0;i-1){
var objinpoutput=output.filter(函数(obj){
if(obj.id==current.id){
返回obj;
}
})[0];
var dataObj={score:current.score,source:current.source};
objinpoutput.data.push(dataObj);
}否则{
var outputObject={name:current.name,id:current.id};
outputObject.data=[{score:current.score,source:current.source}];
output.push(outputObject);
id.push(当前的id);
}
}
返回输出;
}

纯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;
}
函数组objectsbyid(数组){
var输出=[];
var-id=[];
对于(var i=0;i-1){
var objinpoutput=output.filter(函数(obj){
if(obj.id==current.id){
返回obj;
}
})[0];
var dataObj={score:current.score,source:current.source};
objinpoutput.data.push(dataObj);
}否则{
var outputObject={name:current.name,id:current.id};
outputObject.data=[{score:current.score,source:current.source}];
output.push(outputObject);
id.push(当前的id);
}
}
返回输出;
}

这是真正的火箭科学+1这是真正的火箭科学+1感谢@all。。。我将使用这个解决方案。。。原因仍然存在,这一点有待改进:运行过滤器函数总是会降低性能,尤其是当原始数组包含许多对象时。我的解决方案缓存ID,这使它更快。谢谢@all。。。我将使用这个解决方案。。。原因仍然存在,这一点有待改进:运行过滤器函数总是会降低性能,尤其是当原始数组包含许多对象时。我的解决方案缓存ID,这使它更快。