简体   繁体   中英

how do I create an array of objects with array in the object from an object with the same key in javascript

I have an array of objects that looks like this

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

I want to be able to produce something like this, I have been trying hard but I do not seems to get a hang of it.

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

How do I go about solving this problem?

One possible approach:

_.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 . It's a common method when you need to group things up.

Here's a pure javascript solution: use reduce method on the initial array using as the accumulator the result array (empty at first) which will store the transformed data. And as reduce method loops through the items of the initial array, check if the result array contains an element with id of the current item. If so, then just add new data to it, else create a new item in the result array.

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

This version uses groupBy to group the items by id and then maps across each grouping to create the required object:

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

Plain Javascript solution, only working for your specific data structure though:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM