3

I have an object array that has two fields id, and the type of action permission

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},
]

I want to convert this in to the following array:

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 Answers 4

3

You can iterate over the array using Array#reduce while updating a Map where the id is the key and its resulting object is the value.

In the end, you would have the grouped objects per id as the values in this map:

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

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

Comments

0

Here's a working example which also uses array.reduce but plain object instead of javascript Map object. The solution is also not minified.

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)

Comments

0

Another example, maybe not as elegant as using reduce, but a simple version using for of and a map data type.

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)

Comments

0

Just for some exercise; .reduce() and Object.assign() can be handy. The thing is, the resulting array will be a sparse one with object items occupying the indices with the corresponding id values.

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

Now this is only a half measure. If you deal with the sparse arrays then you should make sure that the proper and efficient way to traverse them later on is to use a for in loop or Object.keys(). Otherwise you may waste huge amounts of time checking the holes if the ids are very sparse. i.e. One id being 1 and the next one being 10000000. Besides, the .length property will also include the unused indices. Not ideal.

Then you may think why exactly we need an array to group them under if we will end up with a sparse array? So one good idea would be to group them under another object. This might turn out to be a better abstraction as per your logic. So just do like;

g = a.reduce((c,o) => ( c[o.id] = c[o.id] ? Object.assign(c[o.id],o)
                                          : o
                      , c
                      ),{});

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.