Leia_Organa
Leia_Organa

Reputation: 2094

Array.reduce() on an array of objects -- getting back strings of single letters

I'm working to understand Array.reduce() in JavaScript. I have an array of objects that I'm trying to apply .reduce() to, but I'm getting back an array of single letter strings.

Goal:

["Stuff", "necklace", "ring", "bracelet"]

Current Array of Objects

const productArray =
[
    {
        id: 1,
        productTitle: "Necklace"
    },
    {
        id: 2,
        productTitle: "Ring"
    },
    {
        id: 3,
        productTitle: "Bracelet"
    }
]

Function call

const newStuff = productArray.reduce(function(a, currentValue) {
    return [...a, ...currentValue.productTitle];
}, ["Stuff"])

Actual result: weirdArray

What do I need to do to specify that I don't want "productTitle" broken down into single-letter strings? I have been looking for resources regarding .reduce() on an array of objects but I haven't found anything very helpful. Any pointers?

Upvotes: 2

Views: 7956

Answers (5)

Ori Drori
Ori Drori

Reputation: 191976

To concatenate an array and value when using spread to create a new array, you spread the previous array to the new array, and add the new item without spreading it.

const productArray = [{"id":1,"productTitle":"Necklace"},{"id":2,"productTitle":"Ring"},{"id":3,"productTitle":"Bracelet"}];

const newStuff = productArray.reduce((a, currentValue) => 
  [...a, currentValue.productTitle], []);

console.log(newStuff);

In this case, it's better to use Array.map():

const productArray = [{"id":1,"productTitle":"Necklace"},{"id":2,"productTitle":"Ring"},{"id":3,"productTitle":"Bracelet"}];

const newStuff = productArray.map((currentValue) => currentValue.productTitle);

console.log(newStuff);

Upvotes: 5

RobG
RobG

Reputation: 147363

The use of spread in this case is unnecessary and inefficient as it creates a new accumulator array from the previous one on every iteration. You can remove spread (and fix your issue) and use concat instead to keep it as a one-liner.

However, since you're just adding one new value on each iteration, you should use push. It requires one more line of code but is likely more efficient than using concat.

var productArray = [{id: 1,productTitle: "Necklace"},
                    {id: 2,productTitle: "Ring"},
                    {id: 3,productTitle: "Bracelet"}
];

// Using concat
var newStuff = productArray.reduce((acc, value) =>
  acc.concat(value.productTitle),
["Stuff"]);

console.log(newStuff);

// Using push
var newStuff = productArray.reduce((acc, value) => {
  acc.push(value.productTitle);
  return acc;
}, ["Stuff"]);

console.log(newStuff);

Upvotes: 0

Scott Sauyet
Scott Sauyet

Reputation: 50787

Other answers have pointed out why your code is wrong. But I do want to also note that what you're doing is already covered by Array.prototype.concat:

const productArray = [{"id":1,"productTitle":"Necklace"},{"id":2,"productTitle":"Ring"},{"id":3,"productTitle":"Bracelet"}];

const newStuff = productArray.reduce((a, val) => a.concat(val.productTitle), ['Struff']);
console.log(newStuff);

(And of course, as another answer has mentioned, this sounds more like a use for map than reduce, which might not matter since you're using this to learn reduce.)

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386560

Basically a string is iterable, because the iterator is implemented and returns an array of single characters, if using spread syntax ....

Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

console.log([...'foo']);

Upvotes: 0

Zlatko
Zlatko

Reputation: 19569

Do not spread the title, pass it as it is:

const newStuff = productArray.reduce(function(a, currentValue) {
  return [...a, currentValue.productTitle];
}, ["Stuff"]);

...currentValue.productTitle spreads into an array of individual letters, you only want to spread a variable, the aggregate here.

Upvotes: 0

Related Questions