-2

I am struggling with this problem, I have an array:

['a', 'b', 'c', 'a']

I want to have a something like this:

[ {key: 'a', value: 2}, {key: 'b', value: 1}, {key: 'c', value: 1} ]

I managed to get an object from my array using Arrays.reducer:

{a: 2, b: 1, c: 1} 

Here is the code I used :

myArray.reduce((occurrences, item) => {
        occurrences[item] = (occurrences[item] || 0) + 1;
        return occurrences;
      }, [])

but I am struggling with transforming it to the array I want.

How would you perform this?

CommonPeople
  • 700
  • 1
  • 6
  • 16
  • 2
    `Object.entries` from the object you created ? – Psidom Aug 09 '21 at 16:47
  • I'm a bit surprised because this step seems much easier than the one you've already done. I'm sure there are lots of ways but the first one that comes to mind is iterating through the object with a `for...in` loop and pushing single-key objects to an array that starts off empty. Or you could `map` over `Object.entries` of that intermediate object. Probably other ways too... – Robin Zigmond Aug 09 '21 at 16:48
  • There are many questions around this on Stack Overflow. Please show what research you've done and what attempts you've made to solve the problem yourself. – Heretic Monkey Aug 09 '21 at 16:49
  • Does this answer your question? [How to count duplicate value in an array in javascript](https://stackoverflow.com/questions/19395257/how-to-count-duplicate-value-in-an-array-in-javascript) – Heretic Monkey Aug 09 '21 at 16:54
  • @CommonPeople, simple `.map` after your `.reduce` will get your job done. Have a look on my below answer – A l w a y s S u n n y Aug 09 '21 at 17:08

5 Answers5

2

Adding to your attempt, Just run a map over the keys from the reduced values to get the expected output.

const arr = ["a", "b", "c", "a"];
const reduced = arr.reduce((occurrences, item) => {
  occurrences[item] = (occurrences[item] || 0) + 1;
  return occurrences;
}, {});

const result = Object.keys(reduced).map((item) => {
  return { key: item, value: reduced[item] };
});
console.log(result);
joy08
  • 9,004
  • 8
  • 38
  • 73
1

Simple, use .reduce in a bit different way

const data = ['a', 'b', 'c', 'a'];

const result = data.reduce((acc, cur) => {
  const doesKeyExist = acc.find(a => a.key === cur);
  if(doesKeyExist) {
    doesKeyExist.value += 1
  } else {
    acc.push({
      key: cur,
      value: 1
    })
  }
  return acc;
}, []);

console.log(result);

// [
//   { key: 'a', value: 2 },
//   { key: 'b', value: 1 },
//   { key: 'c', value: 1 }
// ]
AdityaParab
  • 7,024
  • 3
  • 27
  • 40
1

Not the best answer but will do the trick.

const data = []
const arr = ['a', 'b', 'c', 'a']

const occurrencesOf = (number,numbers) => numbers.reduce((counter, currentNumber)=> (number === currentNumber ? counter+1 : counter),0)
const uniq = [...new Set(arr)]
const a = uniq.map(i => ({key: i, value: occurrencesOf(i, arr)}))
console.log(a) // [ {key: 'a', value: 2}, {key: 'b', value: 1}, {key: 'c', value: 1} ]
francis
  • 3,852
  • 1
  • 28
  • 30
0
var values = ['a', 'b', 'c', 'a'];

// get unique values in the array
var output = values.filter((value, index, array) => array.indexOf(value) === index)
    // map them to your desired object, then get the length
    .map(key => ({
        key,
        value: values.filter(x => x === key).length
    }));
    
console.log(output);
Mathew Berg
  • 28,625
  • 11
  • 69
  • 90
0

You can use .map() to make the array of individual objects like below.

Note: As you already managed to get an object from my array using .reduce. So using .map after your reduce, you can get it done easily.

const occurrences = ['a', 'b', 'c', 'a'].reduce(function(acc, curr) {
  return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc
}, {});

const result = Object.entries(occurrences).map((e) => ( { "key": e[0], "value": e[1] } ));
console.log(result)
A l w a y s S u n n y
  • 36,497
  • 8
  • 60
  • 103
  • (not a down voter) Probably because this is a 2 step solution (reduce + map). But don't see any reason for down vote. – AdityaParab Aug 09 '21 at 16:57