Reputation: 23
I'm trying to write a test and I have an array of objects which look something like this:
menuOfProducts: [
{ text: 'Product One',
selector: '#product-one #productone',
path: 'productone' },
{ text: 'Product Two',
selector: '#product-two #producttwo',
path: 'shop/catalog/producttwo' },
{ text: 'Product Three',
selector: '#product-three #productthree',
path: 'shop/catalog/productthree' },
{ text: 'Product Four',
selector: '#product-four #productfour',
path: 'shop/catalog/productfour' },
{ text: 'Product Five',
selector: '#product-five #productfive',
path: 'shop/catalog/productfive' }
]
What I would like to do is filter out a couple of the objects and return the rest.
So far I have tried to use .filter() to filter out one of the objects which works fine. However it may be required to filter out more than one product by text. This is what I have now:
if (environment === 'test') {
menuOfProducts = menuOfProducts.filter(function (option) {
return option.text !== 'Product Two';
});
}
And using this filter I get the correct array returned minus "Product Two":
[
{ text: 'Product One',
selector: '#product-one #productone',
path: 'productone' },
{ text: 'Product Three',
selector: '#product-three #productthree',
path: 'shop/catalog/productthree' },
{ text: 'Product Four',
selector: '#product-four #productfour',
path: 'shop/catalog/productfour' },
{ text: 'Product Five',
selector: '#product-five #productfive',
path: 'shop/catalog/productfive' }
]
But as mentioned above I would like to now filter multiple objects out by text. And was wondering how can I approach this? I have tried passing in another condition in the filter like this:
if (environment === 'test') {
menuOfProducts = menuOfProducts.filter(function (option) {
return option.text !== 'Product Two' || 'Product Three';
});
}
But then I get the array returned with ALL object and nothing is filtered out. Any help would be greatly received. Many thanks in advance
Upvotes: 0
Views: 56
Reputation: 33439
You are using the logic operators wrong. You use it in a way that a real person might understand, but a computer has to be treated differently.
Your logic term: option.text !== 'Product Two' || 'Product Three';
I shorten this to A !== B || C
The operator precedence makes that equivalent to this: (A !== B) || C
This translates to 'A not equal to B else C'
So if A !== B
is true, the whole term has the value of true (because true || anything
is always true
). But if A !== B
is false, the whole term will evaluated to V
(because false || anything
is always anything
)
So you will either have the value true
of C
, C
is the string 'Product Three'
which is a truthy value.
In the end your full term option.text !== 'Product Two' || 'Product Three'
will always be true, thus nothing is filtered out
What you need is A !== B && A !== C
, which is evaluated like (A !== B) && (A !== C)
In this case the term will only be true id option.text
is neither equal to 'Product Two'
nor to 'Product Three'
So your term must be option.text !== 'Product Two' && option.text !== 'Product Three'
console.clear()
menuOfProducts = [
{ text: 'Product One',
selector: '#product-one #productone',
path: 'productone' },
{ text: 'Product Two',
selector: '#product-two #producttwo',
path: 'shop/catalog/producttwo' },
{ text: 'Product Three',
selector: '#product-three #productthree',
path: 'shop/catalog/productthree' },
{ text: 'Product Four',
selector: '#product-four #productfour',
path: 'shop/catalog/productfour' },
{ text: 'Product Five',
selector: '#product-five #productfive',
path: 'shop/catalog/productfive' }
]
menuOfProducts = menuOfProducts.filter(function (option) {
return option.text !== 'Product Two' && option.text !== 'Product Three';
});
console.log(menuOfProducts)
The MDN documentation says:
Operator precedence determines the way in which operators are parsed with respect to each other. Operators with higher precedence become the operands of operators with lower precedence.
This means that we have a sorted list of all possible operators and the operators which are higher in this list are parsed before the lower ones.
We can visualize this with the use of parentheses [(
and )
] which are the Grouping operators and on top of the operator precedence list.
One example A = B + C
This is like A = (B + C)
, because the Assignment operator (single =
) has precedence 3 and the Addition operator (+
) has precedence 13, hence being parsed before the =
Your term was A !== B || C
. Let's take a look at the precedence list
| precedence | operator name | operator |
| 10 | Strict Inequality | !== |
| 5 | Logical OR | || |
The Strict Inequality operator has higher priority than the Logical OR operator. So A !== B || C
is similar to (A !== B) || C
All the operators
Upvotes: 0
Reputation: 35253
You are getting all the values returned because 'Product Three'
is a truthy
value
Use the Logical AND operator like this:
if (environment === 'test') {
menuOfProducts = menuOfProducts.filter(function (option) {
return option.text !== 'Product Two' && option.text !== 'Product Three';
});
}
If you have a multiple option.text
to filter
, you could create an array of those values and use includes
:
if (environment === 'test') {
menuOfProducts = menuOfProducts.filter(function(option) {
return !['Product Two', 'Product Three'].includes(option.text);
});
}
Upvotes: 2
Reputation: 1180
You need to do this:
if (environment === 'test') {
menuOfProducts = menuOfProducts.filter(function (option) {
return option.text !== 'Product Two' && option.text !== 'Product Three';
});
}
Upvotes: 2