【问题标题】:Map array and group by roles in the array object映射数组并按数组对象中的角色分组
【发布时间】:2021-11-05 23:49:46
【问题描述】:

我有一个对象数组,其中我有角色作为键,并且值 init。 现在我想要的是根据角色对它们进行分组。

这是我的数据输入

 {
  users: [
   {
      firstName: 'Will',
      lastName: 'Jacob',
      email: 'sample@sample.com',
      _id: '5e324187b5fdf167a91dfdbb',
      roles: [ 'ward', 'hospital', 'hr' ],
    },
   {
      firstName: 'Theatre',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf2f0c631a8788be59fc4',
      roles: [ 'ward' ],
    },
   {
      firstName: 'Cinema',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: ['hospital', 'hr' ],
    },
    {
      firstName: 'Cinema2',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: ['ward', 'hr' ],
    },
    {
      firstName: 'Cinema3',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: ['hospital', 'hr' ],
    },
    {
      firstName: 'Cinema4',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: [ 'ward', 'hospital', 'hr' ],
    }
]}

我想按角色对它进行分组,并希望输出如下所示的内容

{
    ward: [{
      firstName: 'Will',
      lastName: 'Jacob',
      email: 'sample@sample.com',
      _id: '5e324187b5fdf167a91dfdbb',
      roles: [ 'ward', 'hospital', 'hr' ],
    },
    {   
      firstName: 'Theatre',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf2f0c631a8788be59fc4',
      roles: [ 'ward' ],
    },
    {
      firstName: 'Cinema2',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: ['ward', 'hr' ],
    },
    {
      firstName: 'Cinema3',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: [ 'ward', 'hospital', 'hr' ],
    }],

    hospital: [
    {
      firstName: 'Will',
      lastName: 'Jacob',
      email: 'sample@sample.com',
      _id: '5e324187b5fdf167a91dfdbb',
      roles: [ 'ward', 'hospital', 'hr' ],
    },
    {
      firstName: 'Cinema',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: ['hospital', 'hr' ],
    },
    {
      firstName: 'Cinema3',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: ['hospital', 'hr' ],
    },
    {
      firstName: 'Cinema4',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: [ 'ward', 'hospital', 'hr' ],
    }],

    hr: [{
      firstName: 'Will',
      lastName: 'Jacob',
      email: 'sample@sample.com',
      _id: '5e324187b5fdf167a91dfdbb',
      roles: [ 'ward', 'hospital', 'hr' ],
    },
    {
      firstName: 'Cinema',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: ['hospital', 'hr' ],
    },
    {
      firstName: 'Cinema2',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: ['ward', 'hr' ],
    },
    {
      firstName: 'Cinema3',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: ['hospital', 'hr' ],
    },
    {
      firstName: 'Cinema4',
      lastName: 'Manager',
      email: 'sample@sample.com',
      _id: '5e3cf62cc631a8788be59fc5',
      roles: [ 'ward', 'hospital', 'hr' ],
    }
    ]
}

我怎样才能做到这一点?我正在寻找一个函数来处理它并根据需要返回输出。

【问题讨论】:

  • 您的输入不是有效的 JSON。
  • @Nitheesh 是的,这就是我面临的问题和挑战。
  • 这可以从生成它的脚本或函数中修复,这不会被视为有效的 javascript 对象
  • @Nitheesh 无论如何我要处理好这个问题,我已经更新了问题,你能帮他们分组吗?
  • 您的代码中没有DepartmentUser - 您能详细说明问题所在吗?

标签: javascript node.js arrays json


【解决方案1】:

请找到Array.reduce 实现。

逻辑

  • 遍历数组中的每个对象
  • 循环遍历每个对象中的 roles 数组。
  • 检查累加器是否有一个具有该角色的节点,如果有,则在累加器中推送到该节点,否则创建一个具有该名称和当前对象的节点作为该节点的元素

工作示例

const data = {"users":[{"firstName":"Will","lastName":"Jacob","email":"sample@sample.com","_id":"5e324187b5fdf167a91dfdbb","roles":["ward","hospital","hr"]},{"firstName":"Theatre","lastName":"Manager","email":"sample@sample.com","_id":"5e3cf2f0c631a8788be59fc4","roles":["ward"]},{"firstName":"Cinema","lastName":"Manager","email":"sample@sample.com","_id":"5e3cf62cc631a8788be59fc5","roles":["hospital","hr"]},{"firstName":"Cinema2","lastName":"Manager","email":"sample@sample.com","_id":"5e3cf62cc631a8788be59fc5","roles":["ward","hr"]},{"firstName":"Cinema3","lastName":"Manager","email":"sample@sample.com","_id":"5e3cf62cc631a8788be59fc5","roles":["hospital","hr"]},{"firstName":"Cinema4","lastName":"Manager","email":"sample@sample.com","_id":"5e3cf62cc631a8788be59fc5","roles":["ward","hospital","hr"]}]};

const output = data.users.reduce((acc, curr) => {
  curr.roles.forEach((role) => {
    acc[role] ? acc[role].push(curr) : acc[role] = [curr];
  })
  return acc;
}, {});
console.log(output);

【讨论】:

    【解决方案2】:

    您可以使用array#reduce 根据角色对数据进行分组。您可以遍历每个对象并为每个角色类型创建单独的数组。此解决方案只需要单次遍历您的输入数组。

    const input = { users: [ { firstName: 'Will', lastName: 'Jacob', email: 'sample@sample.com', _id: '5e324187b5fdf167a91dfdbb', roles: [ 'ward', 'hospital', 'hr' ], }, { firstName: 'Theatre', lastName: 'Manager', email: 'sample@sample.com', _id: '5e3cf2f0c631a8788be59fc4', roles: [ 'ward' ], }, { firstName: 'Cinema', lastName: 'Manager', email: 'sample@sample.com', _id: '5e3cf62cc631a8788be59fc5', roles: ['hospital', 'hr' ], }, { firstName: 'Cinema2', lastName: 'Manager', email: 'sample@sample.com', _id: '5e3cf62cc631a8788be59fc5', roles: ['ward', 'hr' ], }, { firstName: 'Cinema3', lastName: 'Manager', email: 'sample@sample.com', _id: '5e3cf62cc631a8788be59fc5', roles: ['hospital', 'hr' ], }, { firstName: 'Cinema4', lastName: 'Manager', email: 'sample@sample.com', _id: '5e3cf62cc631a8788be59fc5', roles: [ 'ward', 'hospital', 'hr' ], }]},
          result = input.users.reduce((r, o) => {
                      o.roles.forEach(role => {
                        r[role] ??= [];
                        r[role].push(JSON.parse(JSON.stringify(o)));
                      });
                      return r;
                  },{});
    console.log(result);

    【讨论】:

    • 我可以在我的代码中替换 ??= 抛出错误
    • 是的,您可以使用r[role] = r[role] || [];
    【解决方案3】:

    您可以遍历每个输入元素,然后遍历输入元素中的每个角色,并将该元素添加到按角色对象中的相应数组中(根据需要创建数组):

    const byRole = {}
    for (const obj of input.users) {
      for (const role of obj.roles) {
        if (!byRole[role]) byRole[role] = []
        byRole[role].push(obj)
      }
    }
    
    console.log(byRole)
    

    如果您愿意,也可以使用一种不那么必要、更实用的方法:

    const byRole = Object.fromEntries(
      [...new Set(input.users.map(obj => obj.roles).flat())]
        .map(role => [role, inputArray.filter(obj => obj.roles.includes(role))])
    )
    
    console.log(byRole)
    

    由于您似乎在使用 MongoDB 记录,另一种可能性是在您的数据库查询中将其分组,将工作卸载到数据库服务器:

    const queryResult = await db.users.aggregate([
      // Optionally add a $match step here to filter: { $match: { ... } }
      { $addFields: { role: '$roles' } },
      { $unwind: '$role' },
      { $group: { _id: '$role', records: { $push: '$$ROOT' } } }
    ])
    const byRole = Object.fromEntries(
      queryResult.map(({ _id, records }) => [_id, records])
    )
    

    (虽然这会在每条记录中留下一个额外的字段role,但我想你不会介意的。)

    【讨论】:

    • 我无法得到预期的结果,你能帮忙;(
    • 请展示您的尝试,如果您不知道您尝试了什么以及失败的原因,我无法提供帮助。
    • 请注意,我的所有建议都直接使用输入 array,这将是您显示的对象的 users 属性的值,而不是整个对象。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-17
    • 2017-08-18
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    相关资源
    最近更新 更多