Given an object like this. How to write a function that will return the object with sorted keys and remove the duplicates from the first value e.g
const initialObj={
"2": ["A", "B", "D", "A"],
"1": ["A", "B", "C"],
};
const output = {
"1": ["C"],
"2": ["A", "B", "D"],
}
initial = {
"1": ["C", "F", "G"],
"2": ["A", "B", "C"],
"3": ["A", "B", "D"],
}
output = {
"1": ["F", "G"],
"2": ["C"],
"3": ["A", "B", "D"],
}
CodePudding user response:
const initialObj= {
"1": ["C", "F", "G"],
"2": ["A", "B", "C"],
"3": ["A", "B", "D"],
}
function sortAndRemove(obj) {
var keys = Object.keys(obj)
keys.sort().reverse()
seenBefore = new Set()
answer = {}
for (var key of keys) {
for (var value of obj[key]) {
if (!seenBefore.has(value)) {
answer[key] = [...(answer[key] || []), value]
seenBefore.add(value)
}
}
}
return answer
}
console.log(sortAndRemove(initialObj))
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Considering the case that I got the algorithm you described, the following snippet would do the trick:
const initial1 = {
"2": ["A", "B", "D", "A"],
"1": ["A", "B", "C"],
};
const initial2 = {
"1": ["C", "F", "G"],
"2": ["A", "B", "C"],
"3": ["A", "B", "D"],
}
// removing duplicates from array
const removeDuplicates = ({
arr,
toRemove
}) => {
return arr.filter(char => !toRemove.includes(char))
}
// returns a sorted array!
const sortObjKeys = (obj) => {
const entries = Object.entries(obj)
const sorted = entries.sort(([key1], [key2]) => {
return Number(key1) - Number(key2)
})
return sorted
}
// iterating over the sorted array (starting from the end)
const reducer = (sorted) => {
const {
ret
} = sorted.reverse().reduce((a, [key, val]) => {
const cleared = removeDuplicates({
arr: [...new Set([...val])],
toRemove: a.toRemove
})
a.ret = [
[key, cleared], ...a.ret,
]
a.toRemove = [...new Set([...a.toRemove, ...val])]
return a
}, {
ret: [],
toRemove: []
})
return ret
}
// putting it all together
const processSortedArr = (obj) => {
const sorted = sortObjKeys(obj)
const ret = reducer(sorted)
return Object.fromEntries(ret)
}
console.log('output1', processSortedArr(initial1))
console.log('output2', processSortedArr(initial2))
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Here is a set of tools
Assuming the keys are strings and not numbers
If you want numerical sort, we need to cast to int
const deDupe = (arr1,arr2) => arr1.filter(val => !arr2.includes(val));
const sortDedupe = obj => {
const newObj = {}
const order = Object.keys(obj); // get the keys
order.sort(); // sort them
order.forEach(key => newObj[key] = obj[key]); // reorder the object
for (let i=0;i<order.length-1;i ) {
newObj[order[i]] = deDupe(newObj[order[i]],newObj[order[i 1]]); //dedupe based on next
}
const last = order.pop()
newObj[last] = [...new Set(newObj[last])]; // dedupe last
return newObj
}
const initialObj={
"2": ["A", "B", "D", "A"],
"1": ["A", "B", "C"],
}; /*
const output = {
"1": ["C"],
"2": ["A", "B", "D"],
}*/
const initial = {
"1": ["C", "F", "G"],
"2": ["A", "B", "C"],
"3": ["A", "B", "D"],
}
/*
output = {
"1": ["F", "G"],
"2": ["C"],
"3": ["A", "B", "D"],
}*/
let output1 = sortDedupe(initialObj)
console.log(output1)
let output2 = sortDedupe(initial)
console.log(output2)
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>