将一个对象映射到多个对象的数组

时间:2020-11-05 14:30:23

标签: javascript node.js arrays json

我需要改变这个:

{
 role:'admin',
 resource:['calendar','appraisal'],
 action:['create:any','read:any','update:any','delete:any']
}
{
 role:'user',
 resource:['calendar','appraisal'],
 action:['create:own','read:any','update:own','delete:own']
}

对此:

[
 {role: 'admin', resource: 'calendar', action: 'create:any'},
 {role: 'admin', resource: 'calendar', action: 'read:any'},
 {role: 'admin', resource: 'calendar', action: 'update:any'},
 {role: 'admin', resource: 'calendar', action: 'delete:any'},
 {role: 'user', resource: 'calendar', action: 'create:own'},
 {role: 'user', resource: 'calendar', action: 'read:any'},
 {role: 'user', resource: 'calendar', action: 'update:own'},
 {role: 'user', resource: 'calendar', action: 'delete:own'},
]

我用Array.map()方法尝试了不同的方法,但是还是没有运气。 我将不胜感激。 谢谢!

4 个答案:

答案 0 :(得分:2)

您可以轻松地使用flatMap

const data = [{
   role:'admin',
   resource:['calendar','appraisal'],
   action:['create:any','read:any','update:any','delete:any']
 },
 {
   role:'user',
   resource:['calendar','appraisal'],
   action:['create:own','read:any','update:own','delete:own']
}];

const mapped = data.flatMap(({role, resource, action}) =>
                 resource.flatMap(resource => 
                   action.map(action => ({role, resource, action}))));

console.log(mapped)

但是,由于这是通用的,因此还会创建appraisal的条目。如果您想跳过它们,则可以使用过滤器轻松地做到这一点:

const calendars = mapped.filter(({resource}) => resource === "calendar");

当然,您也可以通过相同的方式获得评估。这种方法也适用于您将在resource数组中添加的任何其他项目。

答案 1 :(得分:1)

您导致嵌套Array.flatMap()调用(最后一个可以只是映射)来迭代数组(resourceaction)并生成展平的对象数组:

const arr = [{
  role: 'admin',
  resource: ['calendar', 'appraisal'],
  action: ['create:any', 'read:any', 'update:any', 'delete:any']
}, {
  role: 'user',
  resource: ['calendar', 'appraisal'],
  action: ['create:own', 'read:any', 'update:own', 'delete:own']
}]

const result = arr.flatMap(({ resource: res, action: act, ...obj }) =>
  res.flatMap(resource =>
    act.map(action => ({
      ...obj,
      resource,
      action,
    }))
  )
)

console.log(result)

答案 2 :(得分:0)

使用reduce,这样的事情可能会起作用

const json = [
    {
        role:'admin',
        resource:['calendar','appraisal'],
        action:['create:any','read:any','update:any','delete:any']
   },
   {
        role: 'user',
        resource:['calendar','appraisal'],
        action:['create:own','read:any','update:own','delete:own']
    }  
];

const getOutput = (arr) => {
    return arr.reduce((acc, cur) => {
        const roleOutput = cur.action.reduce((actionAcc, actionCur) => 
            [
                ...actionAcc,
                ...cur.resource.map(resVal => ({
                    role: cur.role,
                    resource: resVal,
                    action: actionCur
                }))
            ]
        , []);
            
        return [...roleOutput, ...acc];
    }, []);
}

console.log(getOutput(json));

答案 3 :(得分:0)

我假设您的输入是一个对象数组(因此,第一个代码块将放在方括号中)。您可以创建一个空数组作为累加器,并在遍历输入过程中将元素压入该数组,也可以使用[].concat(...)作为单个语句获取输出。也许后者更有趣:

flatten = arr => [].concat(...arr.map(obj =>
  obj.action.map(a =>
    ({
      role: obj.role,
      resource: obj.resource[0],
      action: a
    }))))

console.log(flatten([{
    role: 'admin',
    resource: ['calendar', 'appraisal'],
    action: ['create:any', 'read:any', 'update:any', 'delete:any']
  },
  {
    role: 'user',
    resource: ['calendar', 'appraisal'],
    action: ['create:own', 'read:any', 'update:own', 'delete:own']
  }
]))

这将为您提供所需的输出,尽管正如一个注释者所指出的那样,似乎您正在忽略除resource属性的第一个元素以外的所有内容。要输出所有排列的列表(会有16个)会更加麻烦,但是可能会应用相同的策略。可以以某种方式将其推广,并创建一个处理所有情况的递归函数!