0

I need to transform this:

{
 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']
}

Into this:

[
 {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'},
]

I've tried in different ways with the Array.map() method but still no luck. I would appreciate any answers. Thanks!

2
  • 3
    Why isn't appraisal taken into account? Are we supposed to only take resource[0] into account? Commented Nov 5, 2020 at 14:45
  • Well no, not really appraisal will be taken into account just didn't write it to make a smaller snippet Commented Nov 5, 2020 at 15:07

4 Answers 4

2

You can easily do so using 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)

However since is generic this is will create also the entries for appraisal. If you want to skip them you can easily do it after, with a filter:

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

Of course you can also obtain the appraisals in the same way. This approach will also work for any other item you'll add in resource array.

Sign up to request clarification or add additional context in comments.

4 Comments

I'm glad to learn about the flatMap method ... I guess an alternative to filtering later is data.flatMap(({role, resource, action}) => action.map(action => ({role, resource: resource[0], action})))
Yeah, but it means you have to stick with the first value of the resource array: what if the order is not consistent across the items? What if "calendar" is not the first? To be fair is still possible to filter upfront, but it would be a bit more code to write, and it will make sense if the items starts to be a lot.
I keep getting this error: flatMap does not exist on type {role: string, resource: string[], action:string[]}[]
@DiegoPlata looks like it was added in ECMAScript 2019: tc39.es/ecma262/#sec-array.prototype.flatmap ... so you would get that error with an older environment
1

You cause nest Array.flatMap() calls (the last one can be just map) to iterate the arrays (resource, action) and generate a flattened array of objects:

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)

3 Comments

Not sure if this is what required. Right?
It seems that into this: shows the expected result
Yes that is what it is required but I keep getting this error: flatMap does not exist on type {role: string, resource: string[], action:string[]}[] and I really don't know why
0

I assume your input is an array of objects (so, that first code block would be enclosed in square brackets). Either you create an empty array as an accumulator and push elements to it as you iterate through your in put, or you could use [].concat(...) to get an output as a single statement. Maybe the latter is more interesting as an answer:

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']
  }
]))

That gives you the output you are looking for, although as one commenter pointed out, it looks as though you are ignoring everything other than the first element of the resource property. Would be a bit more convoluted to output a list of all permutations (there would be 16), but the same strategy might apply. One could generalize this somehow and make a recursive function that handles all cases!

Comments

0

using reduce, something like this could work

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));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.