I have an array of objects that may or not contain a property.
So, in order to filter it, I do this:
array = array.filter(v => v.myproperty != undefined);
array = array.filter(v => v.myproperty[0] != undefined);
This effectively removes the ones where myproperty
is undefined and, afterwards, the ones where the first element inside myproperty
.
Is there a way of having a single liner that prevents me from applying filter
to the array twice?
Something like:
array = array.filter((v => v.myproperty || [])[0] != undefined);
I have an array of objects that may or not contain a property.
So, in order to filter it, I do this:
array = array.filter(v => v.myproperty != undefined);
array = array.filter(v => v.myproperty[0] != undefined);
This effectively removes the ones where myproperty
is undefined and, afterwards, the ones where the first element inside myproperty
.
Is there a way of having a single liner that prevents me from applying filter
to the array twice?
Something like:
array = array.filter((v => v.myproperty || [])[0] != undefined);
Share
Improve this question
asked Aug 23, 2017 at 16:12
chiapachiapa
4,41211 gold badges70 silver badges108 bronze badges
8
-
5
Wouldn't
array = array.filter(v => v.myproperty != undefined && v.myproperty[0] != undefined);
work? – Blorgbeard Commented Aug 23, 2017 at 16:14 - No, that would error: "myproperty is not defined" as it is trying to access index 0 of something undefined – chiapa Commented Aug 23, 2017 at 16:18
-
3
But
&&
short-circuits, right? Ifmyproperty
is undefined,myproperty[0]
will not be evaluated. – Blorgbeard Commented Aug 23, 2017 at 16:20 -
1
No problem. But you might want to double-check C#'s behaviour on this, because it definitely short-circuits
&&
too. – Blorgbeard Commented Aug 24, 2017 at 14:47 -
1
That example is bad..
&&
can't short-circuit (in C# or javascript) when the first argument evaluates to true. It doesn't even make sense to say "if something is null AND something.property is null". A better example: dotnetfiddle/CxJPAw - note no NPE. – Blorgbeard Commented Aug 25, 2017 at 15:34
6 Answers
Reset to default 3In the end, array.filter()
takes an anonymous function that is expecting a boolean result. You can do any amount of work inside to determine if the array item should be filtered.
var array = [1, 2, undefined, 3, "some text", [5,6,7],[], [undefined,8]]
array = array.filter(v => {
if (!v) return false;
if (v === "some text") return false;
if (Array.isArray(v) && v.length === 0) return false;
if (Array.isArray(v) && v[0] === undefined) return false;
return true;
});
console.log(array);
What about:
filtered_array = array.filter(element => element.property && element.property[0]);
What the condition do is to evaluate the left part first. If it's true, it will try to evaluate the right part and return the result.
Fiddle here.
You can do what others have already suggested here, the function will return if the first condition fails.
array => array.filter(v => v.ggwp && v.ggwp[0])
You can also use the in operator to acplish the same thing like this:
array => array.filter(v => ('myproperty' in v) && (0 in v.myproperty))
Here's a jsbin with some testcases that pare these two functions to yours.
I'm not sure though that you want to use !=
in your code instead of !==
. Javascript, because of type coercion has weird behaviour.
Something like
array.filter((v => v.myproperty || [])[0] != undefined);
Yes, exactly something like that. You only misplaced one parenthesis:
array.filter( v => (v.myproperty || [])[0] != undefined);
// ^ ^
You can have plex boolean logic in your statement.
let array = [{num: [1]}, {num: [2]}, {num: [3]}, {num: undefined}, {}]
array = array.filter(v => v && v.num && v.num.length)
For readability and testability you may want to break it out into a function that you can test somewhere else.
function predicate(v) {
return v && v.num && v.num.length
}
let array = [{num: [1]}, {num: [2]}, {num: [3]}, {num: undefined}, {}]
array = array.filter(predicate)
You should also check if the properties element is an array. Checking for the property only with element.property[0]
will also be true for strings. Besides that, you can pass anything returning a boolean inside filter, just like you would do in a if statement.
arr.filter(e => 'myproperty' in e &&
Array.isArray(e.myproperty) &&
e.myproperty[0] !== undefined)