如何根据属性值对数组进行分组?

时间:2015-03-24 03:23:39

标签: javascript arrays object

我有两个JavScript对象(PO​​JO):

var first_original = [
  {group: "A", title: "foo1"},
  {group: "A", title: "foo2"},
  {group: "A", title: "foo3"},
  {group: "A", title: "foo4"},
  {group: "B", title: "foo5"},
  {group: "B", title: "foo6"},
  {group: "B", title: "foo7"}
];
var second_original = [
  {group: null, title: "bar1"},
  {group: null, title: "bar2"},
  {group: null, title: "bar3"},
  {group: null, title: "bar4"},
  {group: null, title: "bar5"},
  {group: null, title: "bar6"},
  {group: null, title: "bar7"}
];

我很难将映射它们的方式概念化为以下结构:

var first_copy = [
  {
    header: "A",
    items: [
      {group: "A", title: "foo1"},
      {group: "A", title: "foo2"},
      {group: "A", title: "foo3"},
      {group: "A", title: "foo4"}
    ]
  },
  {
    header: "B",
    items: [
      {group: "B", title: "foo5"},
      {group: "B", title: "foo6"},
      {group: "B", title: "foo7"}
    ]
  }
];
var second_copy = [
  {
    header: null,
    items: [
      {group: null, title: "bar1"},
      {group: null, title: "bar2"},
      {group: null, title: "bar3"},
      {group: null, title: "bar4"},
      {group: null, title: "bar5"},
      {group: null, title: "bar6"},
      {group: null, title: "bar7"}
    ]
  }
];

我试图使用.forEach()

function getRemappedObject(contentList) {
  val lastGroup    = null;
  var currentIndex = 0;
  var groups       = [];
  contentList.forEach(function(item) {
    if (!groups[currentIndex]) {
      groups.push({items: [item]});
    } else {
      groups[currentIndex].items.push(item);
    }
    groups[currentIndex].header = item.group;
    if (item.group && item.group !== lastGroup) {
      lastGroup = item.group;
      currentIndex++;
    }
  });
  return groups;
}

但是这在规范的标题部分失败了。我认为这是睡眠不足但我很好奇是否有更好的方法。我想在没有Underscore或Lodash的情况下解决它。请参阅ECMAScript 5或6。

如何将上述结构映射到预期输出?

1 个答案:

答案 0 :(得分:2)

使用另一个数组来跟踪标题值;

function organise(arr) {
    var headers = [], // an Array to let us lookup indicies by group
        objs = [],    // the Object we want to create
        i, j;
    for (i = 0; i < arr.length; ++i) {
        j = headers.indexOf(arr[i].group); // lookup
        if (j === -1) { // this entry does not exist yet, init
            j = headers.length;
            headers[j] = arr[i].group;
            objs[j] = {};
            objs[j].header = arr[i].group;
            objs[j].items = [];
        }
        objs[j].items.push( // create clone
            {group: arr[i].group, title: arr[i].title}
        );
    }
    return objs;
}

var first_copy = organise(first_original);

如果您可以假设分组始终是字符串,即从不null,您可以通过密钥而不是indexOf查找更有效地执行此操作


ES6可能会让你像其他解决方案一样通过例如Map WeakMap 不允许将基元作为键)