I am trying to filter out countries in an array of objects with unique currency. The country array structure is
[
{
country: "A",
currencies: [{code: "USD"}, {code: "EURO"}]
},
{
country: "B",
currencies: [{code: "AFN"}]
},
{
country: "C",
currencies: [{code: "CND"}, {code: "EURO"}]
},
{
country: "D",
currencies: [{code: "USD"}]
}
]
What I’m trying to achieve is to filter the country array such that the output array contains only countries with unique value like
[
{
country: "B",
currencies: [{code: "AFN"}]
},
{
country: "C",
currencies: [{code: "CND"}, {code: "EURO"}]
}
]
The countries A and D have both non-unique currency values. In case of country C, even though EURO is non unique, it’s other currency code CND is an unique value. I had used array filter method but couldn’t find a solution. Any help is appreciated.
Advertisement
Answer
You could get an object of grouped objects by code, get only the arrays with a single item, flat the result and get only unique objects as result.
const
data = [{ country: "A", currencies: [{ code: "USD" }, { code: "EURO" }] }, { country: "B", currencies: [{ code: "AFN" }] }, { country: "C", currencies: [{ code: "CND" }, { code: "xEURO" }, { code: "EURO" }] }, { country: "D", currencies: [{ code: "USD" }] }],
result = Object
.values(data.reduce((r, o) => {
o.currencies.forEach(({ code }) => (r[code] ??= []).push(o));
return r;
}, {}))
.filter(a => a.length === 1)
.flat()
.filter((s => o => !s.has(o) && s.add(o))(new Set));
console.log(result);.as-console-wrapper { max-height: 100% !important; top: 0; }A slightly shorter approach
You could get an object of grouped objects by code, with either the index or false, take the values as indices array and filter the data by having a look to the indices array.
const
data = [{ country: "A", currencies: [{ code: "USD" }, { code: "EURO" }] }, { country: "B", currencies: [{ code: "AFN" }] }, { country: "C", currencies: [{ code: "CND" }, { code: "xEURO" }, { code: "EURO" }] }, { country: "D", currencies: [{ code: "USD" }] }],
indices = Object.values(data.reduce((r, o, i) => {
o.currencies.forEach(({ code }) => r[code] = !(code in r) && i);
return r;
}, {})),
result = data.filter((_, i) => indices.includes(i));
console.log(result);.as-console-wrapper { max-height: 100% !important; top: 0; }