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