如何根据属性值对数组进行分组? [英] How do I group an array based on a property value?

查看:60
本文介绍了如何根据属性值对数组进行分组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have two JavScript objects (POJO):

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

我很难概念化如何将它们映射到以下内容结构:

I'm having difficulty conceptualizing how I can map them to the following structure:

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。

But this fails miserably at the header portion of the spec. I think it's lack of sleep but I was curious if there was a better approach. I'd like to solve it without Underscore or Lodash. ECMAScript 5 or 6 please.

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

How do I map the above structures to the expected output?

推荐答案

使用另一个 Array 跟踪标头值;

Use another Array to keep track of the header values;

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

如果您可以假定分组始终是 string ,即从不 null 您可以通过键而不是indexOf查找来更有效地完成操作

If you can assume that the groupings will always be a string i.e. never null you can do it more efficiently by key rather than an indexOf lookup

ES6可能会让您更喜欢通过此处的其他解决方案,例如 地图 WeakMap 不允许基元作为键)

ES6 would probably let you do it more like the other solutions here via e.g. a Map (WeakMap does not permit primitives as keys)

这篇关于如何根据属性值对数组进行分组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆