Why can't I return the result of pushing to the accumulator in a .reduce() function?
Asked Answered
A

4

5

simple example, want to return an array of arrays. For each name in 'peeps' I want to push an array with the word 'hello' into the accumulator.

const peeps = ['sally', 'nick', 'dave'];

return peeps.reduce((acc, val) => {
     return acc.push(['hello'])
  }, []);

It keeps saying that acc.push() is not a function.

Can someone please help me understand why this does not work.

Attentive answered 27/1, 2017 at 9:23 Comment(3)
I realise that I can create an empty array inside the reduce function, push to that and then just return my array instead. But I would like to understand why it doesn't work without what feel like a little hack.Attentive
You could do return acc.concat(['hello']);.Canaliculus
'For each name'... forEach or map looks like a better option in this case. Reduce is for... well...reducing arrays?Ep
C
18

You use Array#push

The push() method adds one or more elements to the end of an array and returns the new length of the array.

this returns the length of the array after pushing. Then the accumulator value is a number, not an array

return acc.push(['hello']) // 1

Solution 1: Return the array instead of the result of pushing.

const peeps = ['sally', 'nick', 'dave'];

console.log(peeps.reduce((acc, val) => {
    acc.push(['hello']);
    return acc;
}, []));

Solution 2: Use Array#concat.

The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.

I would avoid using it with large amounts of data though, as it is a lot less efficient than push. jsPerf

const peeps = ['sally', 'nick', 'dave'];

console.log(peeps.reduce((acc, val) => acc.concat([['hello']]), []));

Solution 3: Use Array#map. This works best, if the result array should have the same length as the given array.

The map() method creates a new array with the results of calling a provided function on every element in this array.

const peeps = ['sally', 'nick', 'dave'];

console.log(peeps.map(val => ['hello']));
Corridor answered 27/1, 2017 at 9:25 Comment(0)
S
1

Try this instead:

const peeps = ['sally', 'nick', 'dave'];

return peeps.reduce((acc, val) => {
    acc.push(['hello']);
    return acc;
}, []);

push does not return acc, you have to do it manually.

Shorthand answered 27/1, 2017 at 9:26 Comment(0)
B
1

I think you should try map. Instead of reduce.

const peeps = ['sally', 'nick', 'dave'];

return peeps.map((val) => {
 return ['hello']
});

It will return an array [ ['Hello'],['Hello'],['Hello'] ]

Reduce is used to get a single value from an array. For example a count, sum, product and so on.

Bordelon answered 27/1, 2017 at 9:30 Comment(1)
It was a contrived example to illustrate my question, I needed to understand it in the context of reduce. You're right though, map is better for my silly example.Attentive
M
0

@Nina's answer is precise and correct.

In addition, recent versions (ES2015 or ES6 and later) of JavaScript supports spread operator syntax that allows you to conveniently return a copy of an array:

const peeps = ["sally", "nick", "dave"];

const output1 = peeps.reduce((acc, _val) => [...acc, "hello"], []); // [ 'hello', 'hello', 'hello' ]

const output2 = peeps.reduce(
  (acc, val) => [...acc, `"hello" from ${val}`],
  []
); // [ '"hello" from sally', '"hello" from nick', '"hello" from dave' ]

That's the preferred way of going about these things these days.

Malversation answered 20/1, 2023 at 20:5 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.