How to include values only once across an array of objects?

I have this array of objects.

[   {     tier1: "Normal",     tier2: "none",     tier3: "none",     tier4: "none",     tier5: "none",   },   {     tier1: "Urgent",     tier2: "GCC & Labour",     tier3: "new",     tier4: "Cancellation",     tier5: "Cancellation",   },   {     tier1: "Urgent",     tier2: "Foreigner",     tier3: "renew",     tier4: "Cancellation",     tier5: "none",   }, ] 

I need to get tier1, tier2, tier3 tier4 and tier5 values only single time.

So suppose in the above example tier1 has Normal one time and Urgent two times so it will be removed in the next element. tier5 has none in the first element so will be reomved from the last element as it already exists.

Output will be

[   {     tier1: "Normal",     tier2: "none",     tier3: "none",     tier4: "none",     tier5: "none",   },   {     tier1: "Urgent",     tier2: "GCC & Labour",     tier3: "new",     tier4: "Cancellation",     tier5: "Cancellation",   },   { tier2: "Foreigner", tier3: "renew" }, ] 
Add Comment
4 Answer(s)

If that’s about re-mapping your source array with filtered copies of items-objects, based on previously seen key/value pairs, you may use Array.prototype.map() in combination with Object.assign() for re-mapping along with Object.keys() together with Array.prototype.reduce() for filtering:

const src = [{tier1:"Normal",tier2:"none",tier3:"none",tier4:"none",tier5:"none",},{tier1:"Urgent",tier2:"GCC & Labour",tier3:"new",tier4:"Cancellation",tier5:"Cancellation",},{tier1:"Urgent",tier2:"Foreigner",tier3:"renew",tier4:"Cancellation",tier5:"none",},],  simplify = (arr, hashMap = []) =>   arr.map(o => Object.assign(     {},     ...Object.keys(o).reduce((r,key) => {       const hash = key+'\ud8ff'+o[key]       if(!hashMap.includes(hash)){         r.push({[key]:o[key]})         hashMap.push(hash)       }       return r     }, [])   ))  console.log(simplify(src))
.as-console-wrapper{min-height:100%;}

Add Comment

Something like this should yield the results you’re looking for.

The runtime, by using a set to track duplicates, should be O(kN) where N is the number of entries in the array and k is the number of keys in each object (here it is 5), which is the tightest bound on this problem.

const data = [{     tier1: "Normal",     tier2: "none",     tier3: "none",     tier4: "none",     tier5: "none",   },   {     tier1: "Urgent",     tier2: "GCC & Labour",     tier3: "new",     tier4: "Cancellation",     tier5: "Cancellation",   },   {     tier1: "Urgent",     tier2: "Foreigner",     tier3: "renew",     tier4: "Cancellation",     tier5: "none",   }, ]  const removeDuplicates = (arr) => {    // retains a set of values for every key   elementSet = {};   return arr.map((elem) => {     const newObj = {};      // iterate over all the keys     for (const key of Object.keys(elem)) {       const value = elem[key];        if (!(key in elementSet)) {         // instantiate the set for the given key         elementSet[key] = new Set();       }        if (!elementSet[key].has(value)) {         // it hasn't been used before, so we can use it, but we'll add to the set for the future         newObj[key] = elem[key];         elementSet[key].add(elem[key]);       }      }     return newObj;   }) }   console.log(removeDuplicates(data))

Add Comment

Maintain Set of values for each key in a object. Use map and get the updated filtered object. (updated object will be keys which are not have already)

const all = {};  const updateObject = (obj) =>   Object.fromEntries(     Object.entries(obj).filter(([key, value]) => {       if (!(key in all)) {         all[key] = new Set();       }       const result = !all[key].has(value);       all[key].add(value);       return result;     })   );  const output = arr => arr.map(updateObject);  data = [   {     tier1: "Normal",     tier2: "none",     tier3: "none",     tier4: "none",     tier5: "none",   },   {     tier1: "Urgent",     tier2: "GCC & Labour",     tier3: "new",     tier4: "Cancellation",     tier5: "Cancellation",   },   {     tier1: "Urgent",     tier2: "Foreigner",     tier3: "renew",     tier4: "Cancellation",     tier5: "none",   }, ];    console.log(output(data));

Add Comment
const data = [{     tier1: "Normal",     tier2: "none",     tier3: "none",     tier4: "none",     tier5: "none",   },   {     tier1: "Urgent",     tier2: "GCC & Labour",     tier3: "new",     tier4: "Cancellation",     tier5: "Cancellation",   },   {     tier1: "Urgent",     tier2: "Foreigner",     tier3: "renew",     tier4: "Cancellation",     tier5: "none",   }, ]  let t1 = [],   t2 = [],   t3 = [],   t4 = [],   t5 = []  data.forEach(d => {   if (!t1.includes(d.tier1)) t1.push(d.tier1)   if (!t2.includes(d.tier2)) t2.push(d.tier2)   if (!t3.includes(d.tier3)) t3.push(d.tier3)   if (!t4.includes(d.tier4)) t4.push(d.tier4)   if (!t5.includes(d.tier5)) t5.push(d.tier5) })  let result = [] for (let i = 0; i < data.length; i++) {   let object = {}   if (t1[i]) object.tier1 = t1[i]   if (t2[i]) object.tier2 = t2[i]   if (t3[i]) object.tier3 = t3[i]   if (t4[i]) object.tier4 = t4[i]   if (t5[i]) object.tier5 = t5[i]   result.push(object) }  console.log(result)

Answered on July 16, 2020.
Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.