Home > OS >  How to filter out object items with unique values in an array in JavaScript
How to filter out object items with unique values in an array in JavaScript

Time:02-19

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.

CodePudding user response:

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

CodePudding user response:

You can use a dictionary code -> country and check, whether code has been set previously. If it has, then the currency is not unique to one country; otherwise it is.

Because I marked non-unique currencies with null, I have to filter them, which I do with Boolean().

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" }] }
];
console.log(getByUniqueCurrencies(data));

function getByUniqueCurrencies(countries) {
  const matchingCountries = Object.values(
    countries.reduce((r, country) => {
      country.currencies.forEach(
        ({ code }) => r[code] = r[code] === undefined ? country : null
      );
      return r;
    }, {})
  ).filter(Boolean);
  return Array.from(new Set(matchingCountries)); // Remove duplicates
}
.as-console-wrapper{max-height:100%!important}

  • Related