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; }