0

I have an object with a structure like below

 const data = [
    { academicYearId: 1, classLevelId: 1, subjectId: 1, ...},
    { academicYearId: 1, classLevelId: 1, subjectId: 2, ...},
    { academicYearId: 1, classLevelId: 1, subjectId: 3, ...},
    ,,,
 ]

I need to create a function that will return unique columns e.g

   const uniqueColumns = ( val, columns)=> {
     //
   }
   const val = [
    { id: 1, name: 'n1', val: 1 },
    { id: 1, name: 'n1', val: 2 },
    { id: 2, name: 'n2', val: 1 },
    { id: 3, name: 'n2', val: 2 }
   ]
   let result = uniqueColumns(val)
   console.log(val)
   /** 
    * Expected
    * [{ id: 1, name: 'n1'}, { id: 2, name: 'n2'}, { id: 3, name: 'n2'}]
    */
}

I have tried to look at the various answers in the post How to get distinct values from an array of objects in JavaScript? and I have managed to come up with the below

   const uniqueColumns = (val, columns) => 
     ([...new Set(
       val.map(item => 
         columns.reduce((prev, next) => 
           ({[next]: item[next], ...prev}), {})
       ).map(item => JSON.stringify(item)))
     ].map(item => JSON.parse(item)))
   
   const val = [
    { id: 1, name: 'n1', val: 1 },
    { id: 1, name: 'n1', val: 2 },
    { id: 2, name: 'n2', val: 1 },
    { id: 3, name: 'n2', val: 2 }
   ]
   const result = uniqueColumns(val, ['id', 'name'])
   console.log(result)

What I was inquiring is if there is a better approach instead of having to Convert Object to string and back to object to achieve this

Owen Kelvin
  • 14,054
  • 10
  • 41
  • 74

1 Answers1

2

You can use array reduce method.

const val = [
  { id: 1, name: "n1", val: 1 },
  { id: 1, name: "n1", val: 2 },
  { id: 2, name: "n2", val: 1 },
  { id: 3, name: "n2", val: 2 },
];

const uniqueColumns = (val, columns) => {
  let ret = val.reduce((p, c) => {
    let obj = {};
    columns.forEach((x) => (obj[x] = c[x]));
    let key = Object.values(obj);
    if (!p[key]) p[key] = obj;
    return p;
  }, {});
  return Object.values(ret);
};

const result = uniqueColumns(val, ["id", "name"]);
console.log(result);
mr hr
  • 3,162
  • 2
  • 9
  • 19
  • That works if I have a fixed column `id`, I am trying to pass a dynamic number of columns to determine the unique entries, something like `uniqueColumns = ( val, ['academicYearId', 'classLevelId'])` will return an array with unique combination of 'academicYearId' and 'classLevelId' – Owen Kelvin Oct 24 '20 at 20:28
  • @Owen Kelvin sorry, I did not see it. – mr hr Oct 24 '20 at 20:35
  • @Owen Kelvin now check and let me know if it is ok. – mr hr Oct 24 '20 at 20:42