Reputation: 1365
I'm trying to accomplish a task with reduce()
that I know how to do with forEach()
. Unfortunately I'm not sure how to structure the syntax and I can't find a good example.
Example 1) In this code I use forEach()
to insert the word species into the first index of each array.
"use strict";
var creatureArray;
creatureArray = [
['zombie', 30, 1, 'bite', 0, 5],
['skeleton', 10, 2, 'sword', 1, 10],
['orc', 15, 4, 'club', 1, 7]
];
creatureArray.forEach(function(value, index, array) {
array[index].unshift('species');
});
console.log(creatureArray);
Example 2) In this code I try to accomplish something similar using .reduce()
. However I know that I'm missing a piece of syntax. I can't figure out how to apply the updated array to the accumulator which is then returned as an object. Thanks so much for any help!
"use strict";
var creatureArray, creatureObject;
creatureArray = [
['zombie', 30, 1, 'bite', 0, 5],
['skeleton', 10, 2, 'sword', 1, 10],
['orc', 15, 4, 'club', 1, 7]
];
creatureObject = creatureArray.reduce(function(accumulator, currentValue, index, array) {
array[index].unshift('species');
//what goes here?
return accumulator;
}, {});
console.log(creatureObject);
Upvotes: 0
Views: 361
Reputation: 31853
Here is how you can do accomplish it.
"use strict";
var creatureArray, creatureObject;
creatureArray = [
['zombie', 30, 1, 'bite', 0, 5],
['skeleton', 10, 2, 'sword', 1, 10],
['orc', 15, 4, 'club', 1, 7]
];
creatureObject = creatureArray.reduce((accumulator, currentValue) => {
return [...accumulator, ['species', ...currentValue]];
}, []);
console.log(creatureObject);
The ...
syntax above is called the Spread Operator.
When applied it expands the elements of the array into the new array created by the enclosing [
and ]
, placing each element from the old array as a top level element into the new array. This results in a flat array instead of a nested array. E.g [[1, 2]]
-> [[1, 2]]
, but [...[1, 2]]
-> [1, 2]
.
This is highly useful because it enables both simple concatenation as well as insertion of top level elements either before or after the expanded array.
Consider:
"use strict";
const names = ['Linus', 'Jane', 'David'];
const withJakeAppended = [...names, 'Jake'];
const withJakePrepended = ['Jake', ...names];
[names, withJakeAppended, withJakePrepended].forEach(xs => console.log(xs));
As you can see, when we spread an Array it is not modified, so the pleasant syntax also enables improved ergonomics for immutable, value oriented programming.
Even better, ...
works with Sets and Maps as well. In fact, it works any Iterable object, including ones we can create ourselves.
I might add that using the fourth argument to either Array.prototype.forEach
or Array.prototype.forEach
is a poor practice that should be avoided.
Note if you need to do this in a browser without ES2015 support, you can write
"use strict";
var creatureArray, creatureObject;
creatureArray = [
['zombie', 30, 1, 'bite', 0, 5],
['skeleton', 10, 2, 'sword', 1, 10],
['orc', 15, 4, 'club', 1, 7]
];
creatureObject = creatureArray.reduce(function (accumulator, currentValue) {
return accumulator.concat([['species'].concat(currentValue)]);
}, []);
console.log(creatureObject);
Upvotes: 3
Reputation: 22876
map
is more apropriate in this case:
var creatureArray = [ ['zombie' , 30, 1, 'bite' , 0, 5],
['skeleton', 10, 2, 'sword', 1, 10],
['orc' , 15, 4, 'club' , 1, 7] ]
var creatureObject = creatureArray.map(currentValue => ['species', ...currentValue] )
console.log( JSON.stringify( creatureObject ).replace(/],/g, '],\n ') )
Upvotes: 2