按对象分组的多个字段
我正在尝试确定最佳数据类型以将对象数组排序为属性定义的组。我有一个对象阵列,如下所示:按对象分组的多个字段
var people = [
{
name: 'Pete',
gender: 'Male',
age: 22
},
{
name: 'Samantha',
gender: 'Female',
age: 20
},
{
name: 'Frank',
gender: 'Male',
age: 22
},
{
name: 'Gary',
gender: 'Male',
age: 21
},
{
name: 'Maria',
gender: 'Female',
age: 20
},
{
name: 'Hannah',
gender: 'Female',
age: 21
},
{
name: 'Pete',
gender: 'Male',
age: 20
}
];
我需要将这些对象分组到任意定义的组中。例如:
- 组1:
gender
- 组2:
age
(这可以由服务器来定义,并且可以改变以包含第三组,如果我们希望。)
然后给我(视觉):
Male:
21:
Gary
22:
Pete
Frank
Female
20:
Samantha
Maria
21:
Hannah
我认为适当的数据类型将是对象的对象。即:
{
Male: {
21: {
[
{
name: 'Gary',
gender: 'Male',
age: 21
}
]
},
22: {
[
{
name: 'Pete',
gender: 'Male',
age: 22
},
{
name: 'Frank',
gender: 'Male',
age: 22
}
]
}
},
Female: {
20: {
[
{
name: 'Samantha',
gender: 'Female',
age: 20
},
{
name: 'Maria',
gender: 'Female',
age: 20
}
]
},
21: {
[
{
name: 'Hannah',
gender: 'Female',
age: 21
}
]
}
}
}
但我不能工作了,对我的生活,适当的算法对这些对象进行排序到数据类型代表的上方。
存在underscore.js
一个有用的工具叫_.groupBy(arr, callback)
,我可以为使用如下:
_.groupBy(people, function (person) {
var props = ['gender', 'age'], // server-defined
prop = [];
for (var i = 0, length = props.length; i < length; i++) {
prop.push(person[props[i]]);
}
return prop.join('|');
});
这给了我,我可以用一个for...in
循环遍历键1 - 深度对象和循环通过构建上面的对象,但这是我坚持的代码。
返回的对象是:
{
"Male|22": [
{
"name": "Pete",
"gender": "Male",
"age": 22
},
{
"name": "Frank",
"gender": "Male",
"age": 22
}
],
"Female|20": [
{
"name": "Samantha",
"gender": "Female",
"age": 20
},
{
"name": "Maria",
"gender": "Female",
"age": 20
}
],
"Male|21": [
{
"name": "Gary",
"gender": "Male",
"age": 21
}
],
"Female|21": [
{
"name": "Hannah",
"gender": "Female",
"age": 21
}
],
"Male|20": [
{
"name": "Pete",
"gender": "Male",
"age": 20
}
]
}
我想的那么通过在管道(|
)对象中的每个关键,分裂循环和使用递归构建包含对象的新对象组/数据数组。
这是实现这个可怕的方式,但我不知道如何去做,否则。
有没有更好的方法我错过了?
也许这可以帮助你。它利用具有对象属性的数组,并将结果按属性的内容分组。
forEach
循环遍历数据。 reduce
循环用于为每个给定组生成分组属性,如果它是最后一个,则返回数组(如果尚未存在)。
最后一步是将其中一个人的值推送到数组中。
var people = [{ name: 'Pete', gender: 'Male', age: 22 }, { name: 'Samantha', gender: 'Female', age: 20 }, { name: 'Frank', gender: 'Male', age: 22 }, { name: 'Gary', gender: 'Male', age: 21 }, { name: 'Maria', gender: 'Female', age: 20 }, { name: 'Hannah', gender: 'Female', age: 21 }, { name: 'Pete', gender: 'Male', age: 20 }],
groups = ['gender', 'age'],
grouped = {};
people.forEach(function (a) {
groups.reduce(function (o, g, i) { // take existing object,
o[a[g]] = o[a[g]] || (i + 1 === groups.length ? [] : {}); // or generate new obj, or
return o[a[g]]; // at last, then an array
}, grouped).push(a);
});
document.write('<pre>' + JSON.stringify(grouped, 0, 4) + '</pre>');
我不同意你的预期输出。我想你应该有Male
和Female
数组属性的对象,并使用此代码来填充数组:
var obj = people.reduce(function (p, c, i) {
p[c.gender].push(c);
return p;
}, { Male: [], Female: [] });
如果你想然后过滤这些阵列可以编写函数是这样的:
function getMaleByAge(obj, age) {
return obj.Male.filter(function (el) {
return el.age === age;
})
}
getMaleByAge(obj, 21); // { name: "Gary", gender: "Male", age: 21 }
由于@andy - 唯一的问题是,该对象可以* *含有多种性质(I使用本实施例以简化的情况)和基团可以是任意水平。因此,每个“人物”对象都可以包含20个属性,我们可能需要将这些属性组织为5个组。合理? – keldar
然后只需按照您认为合适的原始数据进行过滤。只是女人? 'people.filter(function(el){return el.gender ==='Female';});'不是重新整理整个数据集,而是选择需要使用的数据组。 – Andy
即使是21岁的女性:'people.filter(function(el){return el.gender ==='Female'&& el.age === 21;});'。简单。我认为你为自己按计划的方式做了很多工作。希望它能解决不管:) – Andy
使用_.groupBy
& _.map
var output _.map(_.groupBy(people,'gender'),function(obj,key){
var temp = {};
temp[key] = _.groupBy(obj,'age')
return temp;
});
console.log(JSON.stringify(output,null,' '))
会给下面的输出
[{
"Male": {
"20": [
{
"name": "Pete",
"gender": "Male",
"age": 20
}
],
"21": [
{
"name": "Gary",
"gender": "Male",
"age": 21
}
],
"22": [
{
"name": "Pete",
"gender": "Male",
"age": 22
},
{
"name": "Frank",
"gender": "Male",
"age": 22
}
]
}
},
{
"Female": {
"20": [
{
"name": "Samantha",
"gender": "Female",
"age": 20
},
{
"name": "Maria",
"gender": "Female",
"age": 20
}
],
"21": [
{
"name": "Hannah",
"gender": "Female",
"age": 21
}
]
}
}
]
我真的不明白为什么人们总是用框架之类的东西。 香草是faster,这是不是太难代码...
var people = [ { name: 'Pete', gender: 'Male', age: 22 }, { name: 'Samantha', gender: 'Female', age: 20 }, { name: 'Frank', gender: 'Male', age: 22 }, { name: 'Gary', gender: 'Male', age: 21 }, { name: 'Maria', gender: 'Female', age: 20 }, { name: 'Hannah', gender: 'Female', age: 21 }, { name: 'Pete', gender: 'Male', age: 20 }];
var grouped = {}; // final object
for (var i=0,len=people.length,p;i<len;i++) { // faster than .forEach
p = people[i];
if (grouped[p.gender] === undefined) // twice faster then hasOwnProperty
grouped[p.gender] = {};
if (grouped[p.gender][p.age] === undefined)
grouped[p.gender][p.age] = [];
grouped[p.gender][p.age].push(p); // your groupby is HERE xD
}
document.getElementById('grouped').innerHTML = JSON.stringify(grouped, null, 2)
<pre id="grouped"></pre>
这个工程!分组允许任意长度。 :)你能详细描述一下吗? – keldar
我有类似的东西 - 但它非常冗长,想要更简洁的东西:) - 这太棒了! – keldar