refactor map, reduce and double for loop - javascript es6

108
January 23, 2020, at 2:10 PM

I have a JavaScript object, lets say parentObj.

How can I improve the below code. I have a reduce, a map and a double for loop.

[
   {
      NAME: 'SOMENAME',
      ID: '1',
      FROM: '20191223',
      TO: '99991231'
    },
   {
      NAME: 'SOMENAME',
      ID: '2',
      FROM: '20191223',
      TO: '99991231'
   },
   {
      NAME: 'SOMENAME',
      ID: '3',
      FROM: '20191223',
      TO: '99991231'
   }
]

I created a new object.

  const newObj = .reduce(
    function (obj, item) {
      obj[item.NAME] = obj[item.NAME] || [];
      obj[item.NAME].push(item.ID);
      return obj;
    },
    {}
  );

Then a new array of object out of it.

  const newObjArr = Object.keys(newObj ).map(function (key) {
        return { NAME: key, ID: newObj [key] };
      });

And then a double for loop.

      for (let item1 of newObjArr) {
        for (let item2 of parentObj) {
          if (item1.NAME=== item2.NAME) {
            finalObjArr.push({ NAME: item1.NAME, ID: item1.ID, FROM: item2.FROM, TO: item2.TO});
          }
        }
      }

My final output:

[
   {
      NAME: 'SOMENAME',
      ID: [1, 2, 3],
      FROM: '20191223',
      TO: '99991231'
   },
   ...
]
Answer 1

You could use the following:

// sample data 
let parentObj = [{NAME: 'SOMENAME',ID: '1',FROM: '20171223',TO: '99991231'},{NAME: 'SOMENAME',ID: '2',FROM: '20181223',TO: '99991231'},{NAME: 'SOMENAME',ID: '3',FROM: '20191223',TO: '99991231'}]; 
 
let map = new Map(parentObj.map(o => [o.NAME, []])); 
parentObj.forEach(o => map.get(o.NAME).push(o)); 
let finalObjArr = Array.from(map.values(), arr =>  
     arr.map(o => ({...o, ID: arr.map(o => o.ID)})) 
).flat(); 
 
console.log(finalObjArr);

The difference with your own solution is that each ID array in the output will now be independent. So if you would mutate one, that change would not show up in another object.

I used array.flat() which is not in ES6 (you mentioned ES6). If that is an issue, then use [].concat(...array) instead.

Answer 2

You already have that newObj where you can look up things by name. No need to build that newObjArr and loop over it to search by name. Just write

for (const item2 of parentObj) {
  const item1_NAME = item2.NAME;
  const item1_IDs = newObj[item1_NAME];
  finalObjArr.push({ NAME: item1_NAME, ID: item1_IDs, FROM: item2.FROM, TO: item2.TO});
}

Given your updates in the comments, I'd suggest you actually put your objects with all info in the newObj, then all you need to get are its values as an array:

const newObj = parentObj.reduce((obj, item) => {
  if (!(item.NAME in obj))
    obj[item.NAME] = { NAME: item.NAME, ID: [], FROM: item.FROM, TO: item.TO };
  obj[item.NAME].ID.push(item.ID);
  return obj;
}, {});
const finalObjArr = Object.values(newObj);
Answer 3

This might be what you want.

const parentObj = [{ 
    NAME: 'SOMENAME', 
    ID: '1', 
    FROM: '20191223', 
    TO: '99991231' 
}, 
{ 
    NAME: 'SOMENAME', 
    ID: '2', 
    FROM: '20191223', 
    TO: '99991231' 
}, 
{ 
    NAME: 'SOMENAME', 
    ID: '3', 
    FROM: '20191223', 
    TO: '99991231' 
}] 
 
const ids = parentObj.reduce((p,{NAME, ID})=> 
        ((p[NAME] || (p[NAME] = [])), 
         (p[NAME].push(ID)), p), {}) 
 
console.log(parentObj.map(({NAME, FROM, TO})=> 
        ({NAME, ID: ids[NAME], FROM, TO})))

Or this might be what you want. There was a possibility of ambiguity based on your comment on another answer:

const parentObj = [{ 
    NAME: 'SOMENAME', 
    ID: '1', 
    FROM: '20191223', 
    TO: '99991231' 
}, 
{ 
    NAME: 'SOMENAME', 
    ID: '2', 
    FROM: '20191223', 
    TO: '99991231' 
}, 
{ 
    NAME: 'SOMENAME', 
    ID: '3', 
    FROM: '20191223', 
    TO: '99991231' 
}] 
 
console.log(Object.values(parentObj.reduce( 
    (p,{NAME, ID, FROM, TO})=> 
        ((p[NAME] || (p[NAME] = {NAME, ID: [], FROM, TO})), 
         (p[NAME]['ID'].push(ID)), p), {})))

READ ALSO
get multiple count selected

get multiple count selected

I need to count teacher_id selected

115
Flatlist not showing items as intended

Flatlist not showing items as intended

I want to display some items with a flatlist, when I tap on the item I want it to turn greenThe issue I having is that I tap on a couple of the item and then I search for a device, for example: 112

312
how to download multiple images from firestore storage in web [duplicate]

how to download multiple images from firestore storage in web [duplicate]

For webHey is there any possible to download url of files from firestore storage without providing the file name in the storage reference ? Like if we have to download and display all the images from a particular folder, is it must to know the names of all the files uploaded...

128
How to implement webpack's hashed css files into my index.php?

How to implement webpack's hashed css files into my index.php?

I set up a webpack configuration, that uses the MiniCssExtractPlugin to compile my css into a single file into my public folder

121