If you’re anything like me, you wanted to pretend that the JavaScript iterator reduce did not exist. I’ve seen droves, including myself, of budding developers run away from it in fear. However, I’m here to tell you that reduce can be incredibly useful, and you should embrace it!

In this blog, I would like to detail how you can use reduce on a string in order to break it down into an object containing a tally of the word’s letters. Many people think of using reduce strictly to reduce a collection into a single value, but it has many more uses than that. I was asked to do this in my first technical interview, and I’d like to share my process with others.

Initially, reduce is used on an array. Being an iterator function, it is designed to go through an array, producing a desired effect on each index. Lets start with our string:

const word = 'onomatopoeia'

Now let’s start writing our letterTally function!

function letterTally(word){}

Remember, reduce takes in an array, not a string. So, to start, we’re going to split the word by characters. To take into consideration capitalized letters, let’s also lower-case the string before we split it.

function letterTally(word){
const split = word.toLowerCase().split('')
}

Now, we’re ready to reduce! Reduce is going to take in a callback function. This function will have the arguments of the accumulator (acc) and the current value (curr). We’re also going to set the optional argument for reduce: the seed. This seed tells our function what we want the initial accumulator value to be. If this argument is not provided, the initial accumulator defaults to the first value of the passed array. In this case, however, we are going to want to set the seed as an empty object({}).

function letterTally(word){
const split = word.toLowerCase().split('')
return split.reduce( (acc, curr) => {

}, {})
}

Now, for the real breadth of the function: through each iteration, in which we know the element will have the value of a single letter, we’re going to check and see if our object has a property by the name of that letter. If so, we’re going to increment its value. If not, we’re going to set its value to 1. We must return the accumulator in each iteration. Remember that the first value of acc will be equal to the seed that we set, which is an empty object ({}).

function letterTally(word){
const split = word.toLowerCase().split('');
return split.reduce( (acc, curr) => {
if (acc[curr]) {
acc[curr]++;
return acc;
} else {
acc[curr] = 1;
return acc;
}
}, {})
}
const word = 'onomatopoeia'console.log(letterTally(word))
// prints: { o: 4, n: 1, m: 1, a: 2, t: 1, p: 1, e: 1, i: 1 }