I have an array that looks like this:
const subscriptions = [
{
"price": "20",
"product": "apple",
"quantity": 1,
},
{
"price": "10",
"product": "orange",
"quantity": 1,
},
{
"price": "10",
"product": "orange",
"quantity": 1,
},
{
"price": "10",
"product": "orange",
"quantity": 1,
},
]
And I want to pull out all the array elements with a "product" of either apple
, banana
, or pear
.
So I am using filter()
like so:
const currentPlans = subscriptions.filter(
(subscription) =>
subscription.product ===
('apple' || 'banana' || 'pear')
);
Since the array only has once instance of apple
that should be what currentPlans
contains.
But currentPlans
is returning an empty array.
What am I doing wrong?
CodePudding user response:
The following line not going to work as you expect. The right-hand side evaluates one value first(apple
) and then checks equality. It never checks for banana
or pear
.
subscription.product === ("apple" || "banana" || "pear")
You should use another array to keep matches. Try like below.
Using indexOf
const subscriptions = [ { price: "20", product: "apple", quantity: 1, }, { price: "10", product: "orange", quantity: 1, }, { price: "10", product: "orange", quantity: 1, }, { price: "10", product: "orange", quantity: 1, }, ];
const matches = ["apple", "banana", "pear"];
const currentPlans = subscriptions.filter(
(subscription) => matches.indexOf(subscription.product) >= 0
);
console.log(currentPlans);
Using includes
const subscriptions = [ { price: "20", product: "apple", quantity: 1, }, { price: "10", product: "orange", quantity: 1, }, { price: "10", product: "orange", quantity: 1, }, { price: "10", product: "orange", quantity: 1, }, ];
const matches = ["apple", "banana", "pear"];
const currentPlans = subscriptions.filter(
(subscription) => matches.includes(subscription.product)
);
console.log(currentPlans);
CodePudding user response:
When you use conditional checks with respect to the equality check, as per the precedence level, the expression that is present on the right side of the equality check is evaluated first, so when you do 'apple'||'banana'||'pear'
, this statement alone evaluated and then checked against the expression on the left side.
So 'apple'||'banana'||'pear'
would evaluate to be truthy with the value apple
and when you check this value against subscription.product
the filter array would effectively return an object where the value of the property product
is apple
.
const subscriptions = [
{
"price": "20",
"product": "apple",
"quantity": 1,
},
{
"price": "10",
"product": "orange",
"quantity": 1,
},
{
"price": "10",
"product": "orange",
"quantity": 1,
},
{
"price": "10",
"product": "orange",
"quantity": 1,
},
]
const currentPlans = subscriptions.filter(
(subscription) =>
subscription.product ===
('apple' || 'banana' || 'pear')
);
console.log(currentPlans)
Although this would work when filtering objects whose product's value is apple
the logic is technically incorrect when you'd want to filter out values based on conditional checks. As mentioned above the conditional OR
would always return the first value, i.e, apple
, and check this value against each iterable value. In order to actually get this working with conditional checks, you'd have to individually check the value against every other value, like so:
const currentPlans = subscriptions.filter(
(subscription) =>
subscription.product === 'apple' || subscription.product === 'banana' || subscription.product === 'pear'
);
Or, an easier way to accomplish the same would be, by squashing all the values into an array and calling the includes
method and passing the current iterable value as an argument.
const currentPlans = subscriptions.filter(
(subscription) =>
['apple' || 'banana' || 'pear'].includes(subscription.product)
);
CodePudding user response:
Change to
const currentPlans = subscriptions.filter(
(subscription) =>
(subscription.product ===
'apple' || 'banana' || 'pear')
);