-2

How do I calculate the unique values of an object property when I have an array of objects?

let organisations = [
  {
    "id": 1,
    "name": "nameOne",
  },
  {
    "id": 2,
    "name": "nameTwo",
  },
  {
    "id": 3,
    "name": "nameOne",
  }
]

In this case, how do I calculate the number of unique organisation names. The answer here is two, because there are two unique names.

This doesn't work

 var counts = this.filteredExtendedDeals.reduce(
        (organisations, name) => {
          counts[name] = (counts[name] || 0) + 1;
          return counts;
        },
        {}
      );
      return Object.keys(counts);
5
  • reduce or filter Commented Sep 15, 2020 at 15:20
  • @mplungjan You didn't specify an issue with the question but if its the lack of an attempt, that is now included Commented Sep 15, 2020 at 15:23
  • The attempt does not make any sense. You are not running on the same object you show and you are returning outside a function. Please make a minimal reproducible example using the snippet editor. Commented Sep 15, 2020 at 15:25
  • 1
    You can use map with a Set: new Set(organisations.map(({name}) => name)).size; Commented Sep 15, 2020 at 15:27
  • Reduce, no set needed: const names = organisations.reduce((acc,org) => { if (acc.includes(org.name)) return acc; acc.push(org.name); return acc},[]) Commented Sep 15, 2020 at 15:33

1 Answer 1

5

You could reduce the list into a Set and then grab the size.

const organisations = [
  { "id": 1, "name": "nameOne" },
  { "id": 2, "name": "nameTwo" },
  { "id": 3, "name": "nameOne" }
];

const uniqueItems = (list, keyFn) => list.reduce((resultSet, item) =>
    resultSet.add(typeof keyFn === 'string' ? item[keyFn] : keyFn(item)),
  new Set).size;

console.log(uniqueItems(organisations, 'name'));
console.log(uniqueItems(organisations, ({ name }) => name));

If you want to also filter-out null and undefined values:

const organisations = [
  { "id": 1, "name": null },
  { "id": 2, "name": "nameTwo" },
  { "id": 3, "name": undefined }
];

const uniqueItemsNonNull = (list, keyFn) => list.reduce((resultSet, item) =>
    (v => v !== null && v !== undefined ? resultSet.add(v) : resultSet)
    (typeof keyFn === 'string' ? item[keyFn] : keyFn(item)),
  new Set).size;

console.log(uniqueItemsNonNull(organisations, 'name'));
console.log(uniqueItemsNonNull(organisations, ({ name }) => name));

Sign up to request clarification or add additional context in comments.

5 Comments

Why set? const names = organisations.reduce((acc,org) => { if (acc.includes(org.name)) return acc; acc.push(org.name); return acc},[])
@mplungjan A Set is more efficient than checking Array item indices. The lookup is O(1).
@Mr.Polywhirl what if i also do not want to include where name property is empty string. only those that have values?
@chitgoks I added an alternative version to filter-out null and undefined values. I used IIFE syntax to pass the evaluated value i.e. v into an expression.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.