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" }, ]
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%;}
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))
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));
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)