Reputation: 1292
I have a data structure like this:
var example = [
{ name: "item1", year: 2013, value: 100 },
{ name: "item1", year: 2012, value: 97 },
{ name: "item3", year: 2013, value: 93 },
{ name: "item3", year: 2012, value: 91 },
{ name: "item2", year: 2012, value: -6 },
{ name: "item2", year: 2011, value: -5 },
{ name: "item4", year: 2012, value: -36 },
{ name: "item3", year: 2011, value: 93 },
{ name: "item4", year: 2013, value: -35 },
{ name: "item1", year: 2011, value: 98 },
{ name: "item2", year: 2013, value: -7 },
{ name: "item4", year: 2011, value: -37 },
{ name: "item5", year: 2013, value: 58 },
{ name: "item5", year: 2012, value: 55 },
{ name: "item5", year: 2011, value: 54 }
];
I am using this function to get an array of single elements:
example.reduce(function (prev, curr) {
if (prev.indexOf(curr.name) === -1) prev.push(curr.name);
return prev;
}, []);
While this works, I try to use a ternary operator for readability like this:
example.reduce(function (prev, curr) {
return prev.indexOf(curr.name) === -1 ? prev.push(curr.name) : prev;
}, []);
and I get the following error in Chrome:
Uncaught TypeError: prev.indexOf is not a function
at <anonymous>:3:13
at Array.reduce (native)
at <anonymous>:2:9
at Object.InjectedScript._evaluateOn (<anonymous>:895:140)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:828:34)
at Object.InjectedScript.evaluate (<anonymous>:694:21)
Why is that?
Upvotes: 3
Views: 1562
Reputation: 74234
Replace your ternary operator with &&
and ,
instead of ?
and :
as follows:
example.reduce(function (prev, curr) {
return prev.indexOf(curr.name) < 0 && prev.push(curr.name), prev;
}, []);
In this case, instead of using the ternary operator we use logical AND to test whether prev.indexOf(curr.name) < 0
and if so then we do prev.push(curr.name)
. However, we always return prev
because of the comma operator.
As I mentioned in my comment, your code doesn't work because .push
doesn't return the original array. It returns the new length of the array. You could replace .push
with .concat
but it would be very inefficient. The method I described above is better.
Upvotes: 2
Reputation: 388406
it is because calling .push() will return the new length of the array which is a number, so the second call prev
will be a number(1) which don't have the push method.
Returns
The new length property of the object upon which the method was called.
So using the if
condition will be better in your case.
If you want to still use the ternary operator, you can use a hacky solution like
var b = example.reduce(function (prev, curr) {
return prev.indexOf(curr['name']) === -1 ? prev.push(curr['name']) && prev : prev;
}, []);
Upvotes: 5