Reputation: 297
I have an array that looks like this.
var arr = [{
"taxname": "MFM",
"member": [{
"id": 1334,
"name": "Mary G. King",
}, {
"id": 1324,
"name": "Bonnie A. Wilson",
}, {
"id": 1336,
"name": "Samantha B. Sellers",
}]
},
{
"taxname": "Test purpose",
"member": [{
"id": 1336,
"name": "Samantha B. Sellers",
}]
},
{
"taxname": "New_Test_MF",
"member": [{
"id": 1334,
"name": "Mary G. King",
}]
}
];
I have flattened this out so it is just an array of objects.
const result = arr.reduce((r, obj) => r.concat(obj.member), []);
Result:
[{
id: 1334,
name: "Mary G. King"
}, {
id: 1324,
name: "Bonnie A. Wilson"
}, {
id: 1336,
name: "Samantha B. Sellers"
}, {
id: 1336,
name: "Samantha B. Sellers"
}, {
id: 1334,
name: "Mary G. King"
}]
After that remove the duplicate with id from the result, I did.
const ids = result.map(o => o.id)
const filtered = result.filter(({id}, index) => !ids.includes(id, index + 1))
Log the result:
console.log(filtered);
[{
id: 1324,
name: "Bonnie A. Wilson"
}, {
id: 1336,
name: "Samantha B. Sellers"
}, {
id: 1334,
name: "Mary G. King"
}]
I have got the result I wanted. But what is the best way of flattening, the array of objects and returning the unique array instead of using the multiple queries?
Upvotes: 1
Views: 66
Reputation: 561
you can use flat
function in ES10
var arr = [{
"taxname": "MFM",
"member": [{
"id": 1334,
"name": "Mary G. King",
}, {
"id": 1324,
"name": "Bonnie A. Wilson",
}, {
"id": 1336,
"name": "Samantha B. Sellers",
}]
},
{
"taxname": "Test purpose",
"member": [{
"id": 1336,
"name": "Samantha B. Sellers",
}]
},
{
"taxname": "New_Test_MF",
"member": [{
"id": 1334,
"name": "Mary G. King",
}]
}
];
var test = arr.map(a => a.member).flat();
var filterd = [...new Set(test.map(t=>t.id))].map(id => test.find(tt => tt.id === id));
console.log(filterd)
Upvotes: 0
Reputation: 1866
I think the way you did it isn't too bad and it's very readable code! Sometimes it's not about writing the most highly performant code, but about writing readable, easily maintainable and extendible code!
That said, here are some other alternatives:
const existingIds = {};
const result = arr.reduce((r, obj) => r.concat(obj.member.filter((m) => {
if (existingIds.hasOwnProperty(m.id.toString())) {
return false;
}
existingIds[m.id] = true;
return true;
})), []);
As a slight modification to your code, you can use a Set to store non-duplicate IDs. This way in your final step, you don't have to do an includes but a find, although you're not trading much here.
const array2 = arr.reduce((r, obj) => r.concat(obj.member), []);
const nonDuplicateIds = Array.from(new Set(array2.map(m => m.id)))
const result2 = nonDuplicateIds.map(id => array2.find(member => member.id === id)) // You could also use an object for faster lookup
const members = {};
arr.forEach(data => data.member.forEach((member) => members[member.id] = member));
const result3 = Object.values(members);
const result4 = arr.reduce((r, obj) => r.concat(obj.member.filter((m) => r.every(existingM => existingM.id !== m.id))), []);
var arr = [{
"taxname": "MFM",
"member": [{
"id": 1334,
"name": "Mary G. King",
}, {
"id": 1324,
"name": "Bonnie A. Wilson",
}, {
"id": 1336,
"name": "Samantha B. Sellers",
}]
},
{
"taxname": "Test purpose",
"member": [{
"id": 1336,
"name": "Samantha B. Sellers",
}]
},
{
"taxname": "New_Test_MF",
"member": [{
"id": 1334,
"name": "Mary G. King",
}]
}
];
// Alternative #1
const existingIds = {};
const result = arr.reduce((r, obj) => r.concat(obj.member.filter((m) => {
if (existingIds.hasOwnProperty(m.id.toString())) {
return false;
}
existingIds[m.id] = true;
return true;
})), []);
// Alternative #2
const array2 = arr.reduce((r, obj) => r.concat(obj.member), []);
const nonDuplicateIds = Array.from(new Set(array2.map(m => m.id)))
const result2 = nonDuplicateIds.map(id => array2.find(member => member.id === id)) // You could also use an object for faster lookup
// Alternative #3
const members = {};
arr.forEach(data => data.member.forEach((member) => members[member.id] = member));
const result3 = Object.values(members);
// Alternative #4
const result4 = arr.reduce((r, obj) => r.concat(obj.member.filter((m) => r.every(existingM => existingM.id !== m.id))), []);
console.log(result.length);
console.log(result2.length);
console.log(result3.length);
console.log(result4.length);
Upvotes: 2