Unable to make this reduction function work.

Work through Eloquent JavaScript and High Order Functions- section c Functional Programming.

An attempt to define a function reduceand use it in a higher-order function countWords();that takes a given array and counts the number of times each specific value is present and places it in an object.

those. it 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}

those. it does not mean:

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. Thank.

+3
source share
3 answers

The reason is that your implementation ForEachis incorrect. you must set i = 0 ;

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

Something seems to be wrong. You are updating the 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 jsbin here

-2

, , , .

a reduce,

var words = ["foo", "bar", "hello", "world", "foo", "bar"];

var wordIndexer = function(map, word) { 
  map[word] = map[word] || 0;
  map[word]++;
  return map;
};

var count = word.reduce(wordIndexer, {});

console.log(count);

// Object {foo: 2, bar: 2, hello: 1, world: 1}

, , . forEach reduce, , ?


forEach,

var forEach = function(arr, callback) {
  for (var i=0, len=arr.length; i<len; i++) {
    callback(arr[i], i, arr);
  }
  return arr;
};

reduce

var reduce = function(arr, callback, initialValue) {
  var result = initialValue;
  forEach(arr, function(elem, idx) {
    result = callback(result, elem, idx, arr);
  });
  return result;
};

var numbers = [10, 20, 30];

forEach(numbers, function(num, idx) {
  console.log(idx, num);
});

// 0, 10
// 1, 20
// 2, 30
//=> [10, 20, 30]

var n = reduce(numbers, function(sum, num, idx, arr) {
  return sum = sum + num;
}, 0);

console.log(n);
//=> 60

, , native.reduce callback

+4

, , , forEach reduce () / ECMA5 ( ), /.

Array.prototype.forEach(callbackfn [, thisArg])

callbackfn , . forEach callbackfn , , . callbackfn ; .

thisArg, callbackfn. , undefined.

callbackfn : , .

forEach , , callbackfn.

, forEach, callbackfn. , forEach, callbackfn. , , , , ; , forEach , .

forEach , :

  • O - ToObject, .
  • lenValue O [[Get]] "length".
  • len - ToUint32 (lenValue).
  • IsCallable (callbackfn) , TypeError.
  • thisArg , T - Arg; T undefined.
  • k 0.
  • , k < Len
  • Pk - ToString (k).
  • kPresent O [[HasProperty]] Pk.
  • kPresent ,
  • kValue [[Get]] O Pk.
  • callbackfn [[Call]] T , kValue, k O.
  • k 1.
  • undefined.

length forEach 1.

forEach ; , Array. . forEach , .

-

Array.prototype.reduce(callbackfn [, initialValue])

callbackfn , . callback, , , , .

callbackfn : previousValue ( callbackfn), currentValue ( ), currentIndex . previousValue currentValue . initialValue, Value initialValue, currentValue . initialValue , Value , currentValue . TypeError, , initialValue .

reduce , , callbackfn.

, , callbackfn. , , callbackfn. , , callbackfn, , ; , , .

reduce , :

  • O - ToObject, .
  • lenValue O [[Get]] "length".
  • len - ToUint32 (lenValue).
  • IsCallable (callbackfn) , TypeError.
  • len 0, initialValue , TypeError.
  • k 0.
  • initialValue,
  • initialValue.
  • Else, initialValue
  • kPresent false.
  • , kPresent k < Len
  • Pk - ToString (k).
  • kPresent O [[HasProperty]] Pk.
  • kPresent ,
  • [[Get]] O Pk.
  • k 1.
  • kPresent , TypeError.
  • , k < Len
  • Pk - ToString (k).
  • kPresent O [[HasProperty]] Pk.
  • kPresent ,
  • kValue [[Get]] O Pk.
  • callbackfn [[Call]] undefined , , kValue, k O.
  • k 1.
  • .

length 1.

; , Array. . , .

( 100% , ) .

function firstToCapital(inputString) {
    return inputString.charAt(0).toUpperCase() + inputString.slice(1).toLowerCase();
}

function isClass(inputArg, className) {
    return Object.prototype.toString.call(inputArg) === '[object ' + firstToCapital(className) + ']';
}

function checkObjectCoercible(inputArg) {
    if (typeof inputArg === 'undefined' || inputArg === null) {
        throw new TypeError('Cannot convert argument to object');
    }

    return inputArg;
};

function ToObject(inputArg) {
    checkObjectCoercible(inputArg);
    if (isClass(inputArg, 'boolean')) {
        inputArg = new Boolean(inputArg);
    } else if (isClass(inputArg, 'number')) {
        inputArg = new Number(inputArg);
    } else if (isClass(inputArg, 'string')) {
        inputArg = new String(inputArg);
    }

    return inputArg;
}

function ToUint32(inputArg) {
    return inputArg >>> 0;
}

function throwIfNotAFunction(inputArg) {
    if (!isClass(inputArg, 'function')) {
        throw TypeError('Argument is not a function');
    }

    return inputArg;
}

function forEach(array, fn, thisArg) {
    var object = ToObject(array),
        length,
        index;

    throwIfNotAFunction(fn);
    length = ToUint32(object.length);
    for (index = 0; index < length; index += 1) {
        if (index in object) {
            fn.call(thisArg, object[index], index, object);
        }
    }
}

function reduce(array, fn, initialValue) {
    var object = ToObject(array),
        accumulator,
        length,
        kPresent,
        index;

    throwIfNotAFunction(fn);
    length = ToUint32(object.length);
    if (!length && arguments.length === 2) {
        throw new TypeError('reduce of empty array with no initial value');
    }

    index = 0;
    if (arguments.length > 2) {
        accumulator = initialValue;
    } else {
        kPresent = false;
        while (!kPresent && index < length) {
            kPresent = index in object;
            if (kPresent) {
                accumulator = object[index];
                index += 1;
            }
        }

        if (!kPresent) {
            throw new TypeError('reduce of empty array with no initial value');
        }
    }

    while (index < length) {
        if (index in object) {
            accumulator = fn.call(undefined, accumulator, object[index], index, object);
        }

        index += 1;
    }

    return accumulator;
}

function keys(object) {
    if (!isClass(object, 'object') && !isClass(object, 'function')) {
        throw new TypeError('Argument must be an object or function');
    }

    var props = [],
        prop;

    for (prop in object) {
        if (object.hasOwnProperty(prop)) {
           props.push(prop);
        }
    }

    return props;
}

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

var counts = reduce(inputWords, function (previous, element) {
    previous[element] = ++previous[element] || 1;

    return previous;
}, {});

forEach(keys(counts), function (key) {
    console.log(key, this[key]);
}, counts);

jsFiddle

, , .:)

0

All Articles