如何根据属性值对数组进行分组? [英] How do I group an array based on a property value?
问题描述
我有两个JavScript对象(POJO):
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屋!