Can anyone explain how the _.reduce function works within _.contain function? Why is it "false" for the third parameter of the reduce function?
_.contains = function(collection, target) {
return _.reduce(collection, function(wasFound, item) {
if (wasFound) {
return true;
}
return item === target;
}, false);
};
Although that is a working version of _contains
, it is not a very efficient one. It's not the one I see in the Github repo or the different one I see in the annotated source. But it should work, and here's how:
reduce
takes three parameters. (Well, there's an optional fourth, but we can ignore it for these purposes.) The first is the list to reduce, the second is the reducing function, and the third, the one you're asking about, is the initial value of an accumulator.
reduce
at each step after the first passes the reducing function two values: the output of the previous step and the next item in the list. The job of that function is to return the next value, which, at the end of the list is also the final output. But there is no previous value to pass in at the first step. That's what the third parameter is for; it's used to kick off the process. So for this contains
function, the imaginary previous value for the first step is false
. On each step the function checks the previous value. If it's true
, the function simply returns true
. If the list value being tested matches the search value, it returns true
. Otherwise, it returns false
.
Note that this rule means that once you've hit true
, it will stay true
.
The reason I say that this is less than efficient is that we may well know that the list contains the value on checking the very first item. The other implementations mentioned simply return true
at that point. This one continues to process the entire list. Granted it doesn't actually test any more values, as it simply continues to return the true
value along the way, but if the list is long, it's still fairly wasteful when we knew the answer up front.