0
const array = ['w', 'h', 'a', 't', ' ','i', 's','a'];

Let's suppose I'm keeping track of the instances of the letters: a,s,p,y, How can I return the following object by using the reduce method?

{a:2, s:1, p:0, y:0}
Barmar
  • 741,623
  • 53
  • 500
  • 612
Ryu
  • 13
  • 1

3 Answers3

1

Try!

const array = ["w", "h", "a", "t", "i", "s", "a"];

const letters = {
  a:0,
  s:0,
  p:0,
  y:0
};

const result = array.reduce((prev, curr) => {
  if(prev.hasOwnProperty(curr)) prev[curr]++;
  return prev;
}, letters);

console.log(result) // {a:2, s:1, p:0, y:0}

The reduce function takes a total of 2 arguments and can use the second argument as an initial value.

first argument is callback function takes 4 arguments.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

hyundeock
  • 445
  • 1
  • 6
  • 15
0

You can solve it by frequency count.

const array = ["w", "h", "a", "t", " ", "i", "s", "a"];

let ret = array.reduce(
  (p, c) => {
    if (c === "a" || c === "s" || c === "p" || c === "y") {
      p[c]++;
    }
    return p;
  },
  { a: 0, s: 0, p: 0, y: 0 }
);
console.log(ret);
mr hr
  • 3,162
  • 2
  • 9
  • 19
0

There are already some decent answers here but here's another perspective. The reduce method allows us to express a computation on arrays in terms of the answers to two basic questions. If we have confidence in our answers to these questions, then we can have confidence in the entire process itself. This is where reduce truly shines. So, while it's possible to mutate values inside of the function passed to reduce, it negates this benefit. With that in mind, here's an option that avoids mutation in an attempt to highlight this confidence-instilling approach to reduce.

If we frame our desired computation as a question, the key is to answer these two questions:

  1. What is the answer for an empty array?

  2. Given an answer for an array, and an additional element, what is the answer for the augmented array?

Let's look at these one at a time. In our case, the question is: "How do I compute the frequencies of characters in an array?"

  1. Given an empty array, there are no characters to consider and thus no frequencies to report. So the answer here is simply {}.

Now for question 2. Suppose we've computed the frequencies for all the characters in an array called chars. Let's call this partial answer freqs. That is, freqs is some object that correctly describes the frequencies of characters in the chars array.

Now we have a new character (let's call it c), and we need to compute an updated collection of frequencies that accounts for the presence of c. Well, most of the frequencies will remain the same, so here's a good start:

newFreqs = { ...freqs }

...but this isn't the whole story. We also need to account for the new char c. There are two cases to consider: either we've already seen this character before (in which case we already have an entry in our freqs object), or this is the first time we've seen it. In the first case, we need to increment the value associated with the character in freqs, and in the second the frequency is simply 1 (since it's the first time we've come across this character. That might look like this:

newFreqs = {
  // Keep everything the way it is
  ...freqs,
  // except for `c`'s entry, which needs to be incremented or set to 1
  [c]: (freqs[c] || 0) + 1
}

Now that we've answered both of these questions, the rest is simply a matter of arrangement:

function charFreqs(chars) {
  return chars.reduce((freqs, c) => ({
    ...freqs,
    [c]: (freqs[c] || 0) + 1,
  }), {});
}

See here for a demo.

Unsolicited Advertisement: the reduce method codifies the induction property on lists, and this is why it's so powerful (when used without mutation). We're always trying to prove (consciously or unconsciously) that the functions we write behave correctly, and induction is one of the finest tools in this regard.

William Lewis
  • 537
  • 4
  • 9