Search code examples
javascriptforeachreduceecmascript-5polyfills

Can't get this reduce function to work


Working through Eloquent JavaScript and High Order Functions - section in Functional Programming.

Trying to define a reduce function and use it in a higher order function countWords();, which takes a given array and counts number of times each particular value is present and puts it in an object.

I.e. this works:

function combine(countMap, word) {
    countMap[word] = ++countMap[word] || 1; // made the edit

    return countMap;
}

function countWords(wordArray) {
    return wordArray.reduce(combine, {});
}

var inputWords = ['Apple', 'Banana', 'Apple', 'Pear', 'Pear', 'Pear'];

countWords(inputWords); // {Apple: 2, Banana: 1, Pear: 3}

I.e. this does not:

function combine(countMap, word) {
    countMap[word] = ++countMap[word] || 1;

    return countMap;
}

function forEach(array, action) {
    for (var i = 0; i < array.length; i++) {
        action(array[i]);
    }
}

function reduce(fn, base, array) {
    forEach(array, function (element) {
        base = fn(base, element);
    });

    return base;
}

function countWords(wordArray) {
    return reduce(combine, {}, wordArray);
}

var inputWords = ['Apple', 'Banana', 'Apple', 'Pear', 'Pear', 'Pear'];

countWords(inputWords); //    returned this - [object Object] { ... }  - this is no longer an issue after fix keeping it noted for reference to the original issue.

Any help on this would be great. Thanks.


Solution

  • The reason is that your ForEach implementation is wrong. you should set i = 0;

    function forEach(array, action) {
        for(var i = 0; i < array.length; i++) {
            action(array[i]);
        }   
    }
    

    There seems to be something wrong. You update an object. ++countMap

    function combine(countMap, word) {
        countMap[word] = ++countMap || 1;
        return countMap; 
    }
    

    It should be

    function combine(countMap, word) {
        countMap[word] = ++countMap[word] || 1;
        return countMap; 
    }
    

    I add a jsbin here