1

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

var arr = [{'id':21 ,'name' : 'name 1' ,'vehiclename' : 'vehicle 1' ,'parentid' : 21},
           {'id':21 ,'name' : 'name 1' ,'vehiclename' : 'vehicle 2' ,'parentid' : 21},
           {'id':22 ,'name' : 'name 2' ,'vehiclename' : 'vehicle 1' ,'parentid' : 22},
           {'id':22 ,'name' : 'name 2' ,'vehiclename' : 'vehicle 2' ,'parentid' : 22}]

我想将数组展开或分组,现在看起来像这样。

var arr = [{'id':21,
             name: 'name 1'
             vehicles : [{'vehiclename':'vehicle 1','parentid':21},
                         {'vehiclename':'vehicle 2','parentid':21}] },
           {'id':22,
             name: 'name 2'
             vehicles : [{'vehiclename':'vehicle 1','parentid':22},
                         {'vehiclename':'vehicle 2','parentid':22}] }
           }]

任何帮助,将不胜感激。

4

3 回答 3

5

对于那些好奇的人,这里有一个下划线解决方案:

grouped = _.map(_.groupBy(arr, 'id'), function(b) {
    return _.extend(_.pick(b[0], 'id', 'name'), {
        vehicles: _.map(b, function(elem) {
            return _.pick(elem, 'vehiclename', 'parentid')
        })
    });
});

http://jsfiddle.net/bgAzH/1/

于 2013-10-07T09:15:20.403 回答
2

你已经用“underscore.js”标记了你的问题,我相信下划线会让这更容易,但由于我不熟悉它,这里有一个使用Vanilla JS的解决方案:

var working = {},
    output = [],
    id,
    i;

for (i = 0; i < arr.length; i++) {
    id = arr[i].id;
    if (!(id in working))
        working[id] = {id : id, name : arr[i].name, vehicles : []};

    working[id].vehicles.push({vehiclename : arr[i].vehiclename,
                               parentid : arr[i].parentid});
}

for (i in working)
    output.push(working[i]);

// output is now an array of objects in your desired format

我没有直接生成新output数组,而是从一个working对象开始,以便轻松测试是否id已经看到给定的数组。然后我将working对象中的每个项目放入一个实际的数组中。

于 2013-10-07T08:37:14.437 回答
0

我试图让它更具可配置性,看起来不像给定的解决方案那么好,但它自己决定一个属性是否应该是最终对象中的一个数组,还允许配置键以映射到最终对象中的某个键对象,也许这对更通用的情况有帮助。

var _ = require("underscore")

var res = []

var arr = [
  {'id':21 ,'name' : 'name1' ,'vehiclename' : 'vehicle1' ,'parentid' : 21},
  {'id':21 ,'name' : 'name1' ,'vehiclename' : 'vehicle2' ,'parentid' : 21},
  {'id':22 ,'name' : 'name2' ,'vehiclename' : 'vehicle1' ,'parentid' : 22},
  {'id':22 ,'name' : 'name2' ,'vehiclename' : 'vehicle2' ,'parentid' : 22},
]

var connected = [{
  name: "vehicles",
  props: [ "vehiclename", "parentid" ]
}]

arr.forEach(function(e) {
  var obj = _.findWhere(res, { id: e.id })
  if(!obj) {
    obj = { id: e.id }
    res.push(obj)
  }
  var props = _.omit(e, "id");
  connected.forEach(function(cp) {
    props = _.omit.apply(this, [props, cp.props])
  })
  for(p in props) {
    copyPropToObj(props[p], p, obj);
  }
  connected.forEach(function(cp) {
    copyPropToObj(_.pick.apply(this, [e, cp.props]), cp.name, obj)
  })
})

function copyPropToObj(prop, propName, obj) {
  var oProp = _.clone(obj[propName])
  if(oProp && (prop === oProp)) {
    return
  } else if(oProp) {
    // we already have a value, need to move to an array
    obj[propName] = []
    obj[propName].push(prop)
    obj[propName].push(oProp)
  } else {
    // we don't have it set yet so just copy over
    obj[propName] = prop
  }
}

res.forEach(function(e) {
  console.log(e)
})
于 2013-10-07T10:00:07.997 回答