5

I'm working through a tutorial on functional JS and I'm up to a challenge requiring the use of the reduce method:

Given a random array of words, output an array that shows the word plus it's word count, for instance: ['apple', 'orange', 'grape', 'apple'] -> ['apple: 2', 'orange: 1', 'grape: 1']

I know this isn't the correct use of reduce, but here was my semi-working solution:

var wordCountsArray = inputWords.map(function(item) {
    var counter = 0;
    var itemCount = inputWords.reduce(function(prevVal, curVal) {
        if (curVal == item) {
            counter++;
        }
        return;
    }, 0);

    return item + ": " + counter;
})

console.log(wordCountsArray);  

This did indeed output the word counts, but the word count list has duplicates, i.e. looks like:

['apple: 2', 'orange: 1', 'grape: 1', 'apple: 2']

instead of

['apple: 2', 'orange: 1', 'grape: 1']

I've looked up MSDN's guide on the method, Mozilla's, several blogs. I get how it works as an accumulator, but because it uses the output of the last iteration as input for the next, I have no idea how to apply it to this task. I don't need a solution, but maybe a little help in understanding?

ThienLD
  • 741
  • 4
  • 14
ZAR
  • 2,550
  • 4
  • 36
  • 66
  • 2
    The result should be an object, so set that as the accumulator, and then see if the given word exists on the object. If not, assign it to the object with the value `1`, otherwise just increment the existing value. Just be sure to return the object on every iteration. It'll become the final value as well too. No need for `.map()` at all. – cookie monster Jun 16 '14 at 21:18
  • you need to give reduce's 2nd argument an object. no wrong use of reduce if it does what you want. – dandavis Jun 16 '14 at 21:34
  • @david , sorry for the duplicate. I tried searching and looking at other questions with the queries "array reduce, reduce method javascript" etc., how better could I have located the duplicate? – ZAR Jun 16 '14 at 21:35
  • I'm honestly not sure, but I searched (from memory) '[javascript count word frequency stackoverflow](https://www.google.co.uk/search?q=javascript+count+word+frequency+stackoverflow&oq=java&aqs=chrome.1.69i57j69i59l2j69i65l3.1736j0j4&sourceid=chrome&es_sm=93&ie=UTF-8),' which seemed to work. – David Thomas Jun 16 '14 at 21:38
  • Aw, I even made an answer! – Monarch Wadia Jun 16 '14 at 21:44
  • Why be so complicated? If you want a simple thing, including all previous comments, why are you not doing something like that: Array.prototype.countDuplicate = function() { var res = {}; for (var i = 0; i < this.length; i++) { if (res[this[i]]) res[this[i]]++; else res[this[i]] = 1; } return res; } ? – Nico Jun 16 '14 at 21:51

1 Answers1

14

I know this is a solution, but sometimes solutions are the best explanations. Follow the "fruitsCount" object in the first block. Note that "fruitsArray" is simply a translation of this object, so that should be very easy to understand.

var fruits = ['apple', 'orange', 'grape', 'apple'].reduce(function(fruitsCount, currentFruit){
    if(typeof fruitsCount[currentFruit] !== "undefined"){
      fruitsCount[currentFruit]++; 
      return fruitsCount;
    } else {
        fruitsCount[currentFruit]=1; 
        return fruitsCount;
    }
}, {});

var fruitsArray = [];
for(var x in fruits){
    fruitsArray.push(x + ": " + fruits[x]);
}

console.log(fruitsArray);
Monarch Wadia
  • 4,400
  • 4
  • 36
  • 37