javascriptarraysduplicatesderived

Count duplicates in an array and return new array with a key value derived from another array in Javascript


Following on from my previous question, I'd like to change and extend the capability of what was suggested.

Here's the data I've got:

const things = [
  {
    id: 1,
    title: 'Something',
    categoryId: 1
  },
  {
    id: 2,
    title: 'Another thing',
    categoryId: 1
  },
  {
    id: 3,
    title: 'Yet another thing',
    categoryId: 2
  },
  {
    id: 4,
    title: 'One more thing',
    categoryId: 4
  },
  {
    id: 5,
    title: 'Last thing',
    categoryId: 4
  }
]

const categories = [
  {
    id: 1,
    title: 'Category 1'
  },
  {
    id: 2,
    title: 'Category 2'
  },
  {
    id: 4,
    title: 'Category 3'
  }
]

Previously I've been shown how to do something along these lines:

const duplicatesCountWithTitle = (things, categories) => {
  const thingsReduced = things.reduce((hash, { categoryId }) => {
    hash[categoryId] = (hash[categoryId] || 0) + 1
    return hash
  }, {})
}

As you'd be able to tell, the problem with this is that it actually returns a new object, and not a new array. Also I'd like to join the categoryTitle from the categories array with the results of the duplicated count from the things array, based on the categoryId matching the id in categories.

  // currently the above returns an object in the structure of:
  // {
  //   1: 2,
  //   2: 1,
  //   4: 2
  // }
  // what I'm after is an array like this:
  // [
  //   { 'Category 1': 2 },
  //   { 'Category 2': 1 },
  //   { 'Category 3': 2 }
  // ]

Thanks in advance, again.


Solution

  • Something like this?

    const newArr = categories.map(category => {
        const count = things.filter(thing => thing.categoryId === category.id).length;
        return { [category.title]: count }
    });
    console.log(newArr);
    

    https://jsfiddle.net/f3x6m12j/