AngularJS 根据属性组合数组中的对象
AngularJS combining objects in array on properties
我有大量对象 (1500+),并且这些对象在其中一个属性上匹配。因此可以减少对象的总数,例如为了在 ng-repeat 中获得更好的性能。
我是 AngularJS 和 JS 本身的新手,非常感谢您的帮助!
我的对象数组(简化)
myArray = [
{
"role": "user111",
"operation": "create",
"concept": "folder"
},
{
"role": "user111",
"operation": "create",
"concept": "task"
},
{
"role": "user111",
"operation": "delete",
"concept": "task"
},
{
"role": "user222",
"operation": "create",
"concept": "folder"
},
{
"role": "user222",
"operation": "create",
"concept": "task"
},
{
"role": "user222",
"operation": "delete",
"concept": "task"
}
]
期望输出
dreamArray = [
{
"role": "user111",
"operation": {
"create": ["folder", "task"],
"delete": ["task"]
}
},
{
"role": "user222",
"operation": {
"create": ["folder", "task"],
"delete": ["task"]
}
}
]
您可以使用散列 table 并存储对组的引用。
var array = [{ role: "user111", operation: "create", concept: "folder" }, { role: "user111", operation: "create", concept: "task" }, { role: "user111", operation: "delete", concept: "task" }, { role: "user222", operation: "create", concept: "folder" }, { role: "user222", operation: "create", concept: "task" }, { role: "user222", operation: "delete", concept: "task" }],
grouped = array.reduce(function (hash) {
return function (r, o) {
if (!hash[o.role]) {
hash[o.role] = {};
r.push({ role: o.role, operation: hash[o.role]});
}
hash[o.role][o.operation] = hash[o.role][o.operation] || [];
hash[o.role][o.operation].push(o.concept);
return r;
};
}(Object.create(null)), []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以使用 forEach()
循环和 thisArg
参数执行此操作。
var myArray = [{"role":"user111","operation":"create","concept":"folder"},{"role":"user111","operation":"create","concept":"task"},{"role":"user111","operation":"delete","concept":"task"},{"role":"user222","operation":"create","concept":"folder"},{"role":"user222","operation":"create","concept":"task"},{"role":"user222","operation":"delete","concept":"task"}]
var result = [];
myArray.forEach(function(e) {
if(!this[e.role]) {
this[e.role] = {role: e.role, operation: {[e.operation]: [e.concept]}}
result.push(this[e.role]);
} else {
var op = this[e.role].operation[e.operation]
if(op) op.push(e.concept)
else this[e.role].operation[e.operation] = [e.concept]
}
}, Object.create(null))
console.log(result)
使用 reduce()
和 find()
var myArray = [{ role: "user111", operation: "create", concept: "folder" }, { role: "user111", operation: "create", concept: "task" }, { role: "user111", operation: "delete", concept: "task" }, { role: "user222", operation: "create", concept: "folder" }, { role: "user222", operation: "create", concept: "task" }, { role: "user222", operation: "delete", concept: "task" }],
const dreamArray = myArray.reduce((acc, item) => {
let obj = acc.find(e => e.role === item.role);
if(!obj){
obj = {"role" : item.role, "operation": {[item.operation]: [item.concept]}};
acc.push(obj);
}else{
obj.operation[item.operation] = obj.operation[item.operation] || [];
obj.operation[item.operation].push(item.concept);
}
return acc;
}, []);
console.log(dreamArray);
正如我在评论中提到的,如果您碰巧收到已经在 role
属性 上排序的数据(您是这么说的),那么所需的操作归结为一个非常简单的操作.reduce()
操作,可以用 O(n) 的时间复杂度实现,如下所示;
var data = [{"role":"user111","operation":"create","concept":"folder"},{"role":"user111","operation":"create","concept":"task"},{"role":"user111","operation":"delete","concept":"task"},{"role":"user222","operation":"create","concept":"folder"},{"role":"user222","operation":"create","concept":"task"},{"role":"user222","operation":"delete","concept":"task"}],
result = data.reduce((r,c,i) => !i || r[r.length-1].role !== c.role ? r.concat({"role": c.role, "operation": c.operation === "create" ? {"create": [c.concept], "delete": []}
: {"create": [], "delete": [c.concept]}})
: r[r.length-1].operation[c.operation].includes(e => e === c.concept) ? r
:(r[r.length-1].operation[c.operation].push(c.concept),r), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我有大量对象 (1500+),并且这些对象在其中一个属性上匹配。因此可以减少对象的总数,例如为了在 ng-repeat 中获得更好的性能。 我是 AngularJS 和 JS 本身的新手,非常感谢您的帮助!
我的对象数组(简化)
myArray = [
{
"role": "user111",
"operation": "create",
"concept": "folder"
},
{
"role": "user111",
"operation": "create",
"concept": "task"
},
{
"role": "user111",
"operation": "delete",
"concept": "task"
},
{
"role": "user222",
"operation": "create",
"concept": "folder"
},
{
"role": "user222",
"operation": "create",
"concept": "task"
},
{
"role": "user222",
"operation": "delete",
"concept": "task"
}
]
期望输出
dreamArray = [
{
"role": "user111",
"operation": {
"create": ["folder", "task"],
"delete": ["task"]
}
},
{
"role": "user222",
"operation": {
"create": ["folder", "task"],
"delete": ["task"]
}
}
]
您可以使用散列 table 并存储对组的引用。
var array = [{ role: "user111", operation: "create", concept: "folder" }, { role: "user111", operation: "create", concept: "task" }, { role: "user111", operation: "delete", concept: "task" }, { role: "user222", operation: "create", concept: "folder" }, { role: "user222", operation: "create", concept: "task" }, { role: "user222", operation: "delete", concept: "task" }],
grouped = array.reduce(function (hash) {
return function (r, o) {
if (!hash[o.role]) {
hash[o.role] = {};
r.push({ role: o.role, operation: hash[o.role]});
}
hash[o.role][o.operation] = hash[o.role][o.operation] || [];
hash[o.role][o.operation].push(o.concept);
return r;
};
}(Object.create(null)), []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以使用 forEach()
循环和 thisArg
参数执行此操作。
var myArray = [{"role":"user111","operation":"create","concept":"folder"},{"role":"user111","operation":"create","concept":"task"},{"role":"user111","operation":"delete","concept":"task"},{"role":"user222","operation":"create","concept":"folder"},{"role":"user222","operation":"create","concept":"task"},{"role":"user222","operation":"delete","concept":"task"}]
var result = [];
myArray.forEach(function(e) {
if(!this[e.role]) {
this[e.role] = {role: e.role, operation: {[e.operation]: [e.concept]}}
result.push(this[e.role]);
} else {
var op = this[e.role].operation[e.operation]
if(op) op.push(e.concept)
else this[e.role].operation[e.operation] = [e.concept]
}
}, Object.create(null))
console.log(result)
使用 reduce()
和 find()
var myArray = [{ role: "user111", operation: "create", concept: "folder" }, { role: "user111", operation: "create", concept: "task" }, { role: "user111", operation: "delete", concept: "task" }, { role: "user222", operation: "create", concept: "folder" }, { role: "user222", operation: "create", concept: "task" }, { role: "user222", operation: "delete", concept: "task" }],
const dreamArray = myArray.reduce((acc, item) => {
let obj = acc.find(e => e.role === item.role);
if(!obj){
obj = {"role" : item.role, "operation": {[item.operation]: [item.concept]}};
acc.push(obj);
}else{
obj.operation[item.operation] = obj.operation[item.operation] || [];
obj.operation[item.operation].push(item.concept);
}
return acc;
}, []);
console.log(dreamArray);
正如我在评论中提到的,如果您碰巧收到已经在 role
属性 上排序的数据(您是这么说的),那么所需的操作归结为一个非常简单的操作.reduce()
操作,可以用 O(n) 的时间复杂度实现,如下所示;
var data = [{"role":"user111","operation":"create","concept":"folder"},{"role":"user111","operation":"create","concept":"task"},{"role":"user111","operation":"delete","concept":"task"},{"role":"user222","operation":"create","concept":"folder"},{"role":"user222","operation":"create","concept":"task"},{"role":"user222","operation":"delete","concept":"task"}],
result = data.reduce((r,c,i) => !i || r[r.length-1].role !== c.role ? r.concat({"role": c.role, "operation": c.operation === "create" ? {"create": [c.concept], "delete": []}
: {"create": [], "delete": [c.concept]}})
: r[r.length-1].operation[c.operation].includes(e => e === c.concept) ? r
:(r[r.length-1].operation[c.operation].push(c.concept),r), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }