Ivonne Terrero Ivonne Terrero - 3 months ago 14
Javascript Question

The use of first last and map to implement Reduce

I stumbled upon this code that is meant to redefine Array.prototype.reduce:



function first(array, n){
return n === undefined ? array[0] : array.slice(0, n);
};

function last(array, n){
if(n> array.length){
return array;
}else{
return n === undefined ? array[array.legnth -1] : array.slice(array.length - n, array.length);

};

function map(collection, iterator){
var arr = [];
each(collection, function(element, index){
arr.push(iterator(element, index);
});
return arr;
};





function reduce(collection, rf, acc) {
acc = acc === undefined ? first(collection) : acc;
return last(map(collection, function (value) {
acc = rf(acc, value);
return acc;
}));
}


However, I don't understand what array.last() is doing here. Can someone please explain. Thank you.

Answer
0:    function reduce(collection, rf, acc) {
1:        acc = acc === undefined ? first(collection) : acc;
2:        return last(map(collection, function (value) {
3:            acc = rf(acc, value);
4:            return acc;
5:        }));
6:    }

Here's a line by line for what's going on in your reduce() function:

Line 1: If no value is passed for acc, set it to the first value in the collection.

Line 2: Call map() on your collection which will iterate over the collection, calling a callback that calls rf() on each item of the collection. map() creates a new array that is the collection of returned values from each time the iteration callback is called. On the resulting array returned from map(), get the last() value from that array and return that as the final return result from reduce().

Line 3: Set acc to be the result of rf(acc, value).

Line 4: Return acc from the callback which map() will put into the array.

However, I don't understand what array.last() is doing here. Can someone please explain.

Assuming you mean last(array), the function of your last(array) is to get the last item in an array. If you pass a second argument to last(), then it gets the last N items from the array you pass in and returns that as a new array (you are not using this second capability).


The implementation of reduce() does not seem like it should use map() because there's no point in creating this internal array. I would think this would be more efficient:

function reduce(collection, rf, initial) {
    var acc = (initial === undefined) ? first(collection) : initial;
    each(collection, function(value) {
        acc = rf(acc, value);
    });
    return acc;
}

If you want to more accurately mimic Array.prototype.reduce() where if no initial value is selected, then the first element in the array is used as the initial value and the iterator is not called for the first element in the array, then you could do this:

function reduce(collection, rf, initial) {
    var acc = initial, index = 0;
    if (initial === undefined) {
        acc = collection[0];
        index = 1;
    }
    for (; index < collection.length; ++index) {
        acc = rf(acc, collection[index]);
    });
    return acc;
}