[英]Group objects in an array by Id - JavaScript
我有一个对象数组,它有两个字段 id 和操作权限的类型
const array=[
{view: false, id: 1},
{create: false, id: 1},
{read: false, id: 1},
{update: false, id: 1},
{delete: false, id: 1},
{view: false, id: 2},
{create: false, id: 2},
{read: false, id: 2},
{update: false, id: 2},
{delete: false, id: 2},
]
我想将其转换为以下数组:
const permissions=[
{
id: 1,
view: false,
read: false,
create: false,
delete:false,
update:false
},
{
id: 2,
view: false,
read: false,
create: false,
delete:false,
update:false
}
]
您可以在更新Map
时使用Array#reduce
迭代数组,其中id
是key
,其结果对象是value
。
最后,您会将每个id
的分组对象作为此映射中的values
:
const array = [ {view: false, id: 1}, {create: false, id: 1}, {read: false, id: 1}, {update: false, id: 1}, {delete: false, id: 1}, {view: false, id: 2}, {create: false, id: 2}, {read: false, id: 2}, {update: false, id: 2}, {delete: false, id: 2}, ]; const res = [... array.reduce((map, { id, ...elem }) => map.set(id, { ...(map.get(id) || { id }), ...elem }) , new Map) .values() ]; console.log(res);
这是一个工作示例,它也使用array.reduce
但普通对象而不是 javascript Map
对象。 解决方案也没有缩小。
const data = [
{ view: false, id: 1 },
{ create: false, id: 1 },
{ read: false, id: 1 },
{ update: false, id: 1 },
{ delete: false, id: 1 },
{ view: false, id: 2 },
{ create: false, id: 2 },
{ read: false, id: 2 },
{ update: false, id: 2 },
{ delete: false, id: 2 },
]
const merged = data.reduce((prev, current) => {
// get the id.
// make it to string as we use it as key and not index!
const id = '' + current.id
// create object if it does not already exist:
if (!prev[id]) {
prev[id] = {}
}
// store the given data, merge it with already
// existing data under the id
prev[id] = {
...prev[id],
...current
}
// return the results.
return prev
}, {})
// now that we have merged togehter the objects,
// extract them and push em together to an array:
const results = Object.keys(merged).map(k => merged[k])
console.log('results', results)
另一个例子,可能不如使用reduce 优雅,而是使用for of 和map 数据类型的简单版本。
const array = [{ view: false, id: 1 }, { create: false, id: 1 }, { read: false, id: 1 }, { update: true, id: 1 }, { delete: false, id: 1 }, { view: false, id: 1 }, { create: false, id: 1 }, { read: false, id: 1 }, { update: false, id: 1 }, { delete: false, id: 1 }] const perm = {} for(let el of array){ const {id} = el perm[id] = perm[id] ? {...perm[id], "id": id} : {"id": id} for(let key in el){ if(key === 'id'){ continue } perm[id] = {...perm[id], [key]: el[key]} } } console.log("Permissions Map:", perm) const permissionsArray = Object.values(perm) console.log("Permissions Array:",permissionsArray)
只是为了一些锻炼; .reduce()
和Object.assign()
可以很方便。 问题是,结果数组将是一个稀疏数组,对象项占据具有相应id
值的索引。
var a = [ {view: false, id: 1} , {create: false, id: 1} , {read: true, id: 1} , {update: false, id: 1} , {delete: false, id: 1} , {view: false, id: 2} , {create: false, id: 2} , {read: false, id: 2} , {update: true, id: 2} , {delete: false, id: 2} ], g = a.reduce((c,o) => ( c[o.id] = c[o.id] ? Object.assign(c[o.id],o) : o , c ),[]); console.log(g);
现在这只是一半的措施。 如果您处理稀疏数组,那么您应该确保稍后遍历它们的正确且有效的方法是使用for in
循环或Object.keys()
。 否则,如果id
非常稀疏,您可能会浪费大量时间检查漏洞。 即一个id
是 1,下一个是 10000000。此外, .length
属性还将包括未使用的索引。 不理想。
那么你可能会想,如果我们最终会得到一个稀疏数组,为什么我们需要一个数组来将它们分组? 所以一个好主意是将它们分组到另一个对象下。 根据您的逻辑,这可能会成为更好的抽象。 所以只是喜欢;
g = a.reduce((c,o) => ( c[o.id] = c[o.id] ? Object.assign(c[o.id],o)
: o
, c
),{});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.