按照Id将对象在数组中分组 - JavaScript

3

我有一个对象数组,它有两个字段: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
}
]
4个回答

3
你可以使用Array#reduce来遍历数组,同时更新一个以idkey、其相对应对象为valueMap
最终,你将会得到一个根据id分组的对象,它们作为这个Map中的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);


0

另一个例子,可能不如使用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)


0

这里有一个工作示例,它也使用了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)

0

只是为了一些练习; .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
                      ),{});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接