Skip to content Skip to sidebar Skip to footer

How To Filter Object Using Array.prototype.filter?

Given var arr = [1,2,true,4,{'abc':123},6,7,{'def':456},9,[10]] we can filter number items within array arr using Number constructor var res = arr.filter(Number); // [1, 2, true,

Solution 1:

How to filter objects with or without Object prototype or constructor within in an array passed to Array.prototype.filter() without using an anonymous function callbackpattern ?

As per spec

callbackfn should be a function that accepts three arguments and returns a value that is coercible to the Boolean value true or false

Number object (function's constructor) does return NaN for bad Number conversion but String and Object constructors don't return a false value (yes, filter(Number) also filters out 0)

var arr = [0,1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]];
arr.filter(Number); //outputs [1, 2, true, 4, 6, 7, 9, Array[1]]

You can create a customer function OBJ,

functionOBJ(value,index,arr){ returntypeof value === "object" && !Array.isArray(value) }

or Arrays are also welcome in the resultset then remove the Array.isArray check

functionOBJ(value,index,arr){ returntypeof value === "object" }

when used with

arr.filter(OBJ); //outputs [{"abc":123},{"def":456}]

Solution 2:

There is no real way to do it safely without creating your own function. Additionally it is very complicated because the definition of Object is too broad.

Let's start with the following:

var types = ['1', 2, true, null, undefined, [], {}, newDate()];

and run the following:

types.map((e) => typeof e);
// ["string", "number", "boolean", "object", "undefined", "object", "object", "object"]

Do you think of null of as an Object? I don't think so. Do you think of an Array as of an Object, because the Arrayis an instance of Object? I am not sure as well.

What you can try is the following:

types.map(Object.isExtensible);
// [false, false, false, false, false, true, true, true]

This excludes the null from the result but still the array is present here. The DateObject is here as well as any other Object with any prototype, e.g. new Boolean() will also be an Object. Additionally the object could be frozen and this won't be returned as an Object here as well.

So the both examples here successfully demonstrate that the definition of Object is too broad and it cannot be really handled in a useful way.

Solution 3:

Without passing a callback function, you can instead pass in a regex by using the RegExp.prototype.test method and binding a regex

var arr = [1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]]

var res = arr.filter(RegExp.prototype.test.bind(/\[object Object\]/));

console.log(res)

This would match any string containing [object Object] as well, but it seems highly unlikely that a string would contain those exact words, unless you have made a mistake and included stringified objects in your array.

Solution 4:

In ES6 the following would do it for the example values you have listed:

arr.filter(Object.isExtensible)

Obviously, this will exclude objects that have been marked non-extensible, by a call to Object.freeze, Object.seal, or Object.preventExtensions. Unless you plan to use those, I believe this does the job.

var arr = [
    /* primitives: */2, true, "str", null, undefined, NaN, 
    /* objects */newNumber(2), {a:1}, Object.create(null), [10], x=>x, newDate(), newSet()
];

var objects = arr.filter(Object.isExtensible);

console.log(objects);

Solution 5:

The closest have been able to reach to requirement so far, also matches Object.create(null)

var res = []; for (let p of arr) /^\{?.+\}$/.test(JSON.stringify(p)) && res.push(p)

Post a Comment for "How To Filter Object Using Array.prototype.filter?"