55

I am trying to filter all the elements in an array which are bigger than 10 to a new array. I am intentionally not using Array.prototype.filter() since I want to learn the reduce() method. Here is the code I was playing with

var collection = [3, 5, 11, 23, 1];

// fileter all the elements bigger than 10 to a new array

var output = collection.reduce(function(filteredArr, collectionElemet) {
  if (collectionElemet > 10) {
    return filteredArr.push(collectionElemet);
  }
}, []);

I was expecting that filteredArr would be initialized with an empty array at the time of first callback execution as it happens with many examples provided here. But when I run this code, I get the error Cannot read property 'push' of undefined, where am I messing it up? Thank you!

2
  • If the condition is true - you return a number, if not true - you return an undefined. If you simply want to filter - use Array.prototype.filter, your current code as it is is ugly and misleading. Commented Sep 18, 2015 at 1:35
  • 1
    @zerkms: That's fair for production code, not for education/experimentation. The OP clearly states that he knows about filter, but is trying to understand reduce. Commented Sep 18, 2015 at 1:39

2 Answers 2

76

When you try to do return filteredArr.push(collectionElement), in essence you are returning length of filteredArr after the push operation. The push() method adds one or more elements to the end of an array and returns the new length of the array. Ref: Array.prototype.push().

You need to return the filteredArr from your anonymous function, so that it is used as the previousValue for the next call

var collection = [3, 5, 11, 23, 1];

// filter all the elements bigger than 10 to a new array

var output = collection.reduce(function(filteredArr, collectionElement) {
  if (collectionElement > 10) {
    filteredArr.push(collectionElement);
  }
  return filteredArr;
}, []);
Sign up to request clarification or add additional context in comments.

Comments

12

Array.prototype.push will return the length of the new array. You need to return the accumulator. A succinct way to do this is with Array.prototype.concat, since that method will actually return the array:

var collection = [3, 5, 11, 23, 1];

var output = collection.reduce(function(filteredArr, collectionElemet) {
  if (collectionElemet > 10) {
    return filteredArr.concat(collectionElemet);
  }
}, []);

You have to return the accumulator so the next iteration can use the value of the accumulator.

2 Comments

Not my downvote, but concat returns a new array every time, which is inefficient. push is the obvious choice for appending new elements to an existing array.
Not always is about efficiency, Is valid answer because illustrate two things, how to make a solution in one line and that @segmentationfaulter must return filteredArr. His confusion probably was thinking that filteredArr.push will return filteredArr.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.