如何使用Array.prototype.filter过滤对象?

时间:2021-10-23 12:36:21

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

我们可以使用Number构造函数过滤数组arr中的数字项

var res = arr.filter(Number); // [1, 2, true, 4, 6, 7, 9, Array[1]]

are true and [10] expected in resulting array ? If we substitute false for true at arr

在结果数组中是真的和[10]期望?如果我们在arr中将false替换为true

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

using Array.isArray

var res = arr.filter(Array.isArray) // [Array[1]]

String

var res = arr.filter(String) // [1, 2, true, 4, Object, 6, 7, Object, 9, Array[1]]

If we want to filter items within arr that are object, at indexes 4 , 7 and we try

如果我们想要在arr中过滤作为对象的项目,请在索引4,7处尝试

var res = arr.filter(Object) // [1, 2, true, 4, Object, 6, 7, Object, 9, Array[1]]

Although we would prefer to simply call arr.filter(Object), we could pass a function call; trying different properties of Object so that we can eventually find a property or method that we could use as a function or constructor to pass to as the pattern arr.filter(/* method, constructor, other approach */) to return the filtered results matching the object, or even property name or value of the object within the input array.

虽然我们更喜欢简单地调用arr.filter(Object),但我们可以传递一个函数调用;尝试Object的不同属性,以便我们最终可以找到一个属性或方法,我们可以将其作为函数或构造函数传递给模式arr.filter(/ *方法,构造函数,其他方法* /)以返回过滤结果匹配对象,甚至是输入数组中对象的属性名称或值。

We start, innocently enough, by checking if the item in the array has a constructor having name equal to "Object"

我们通过检查数组中的项是否具有名称等于“Object”的构造函数来无辜地开始

 var res = arr.filter(function(prop) {
  return prop.constructor.name === "Object"
 }) // [Object, Object]

though when we add an object to arr; e.g.;

虽然当我们向arr添加一个对象时;例如。;

 var c = Object.create(null); arr.push(c); 

 var res = arr.filter(function(prop) {
   return prop.constructor.name === "Object"
 }) // `Uncaught TypeError: Cannot read property 'name' of undefined`

as c prototype and constructor are undefined. Although we are certain that this will not return expected results

因为c原型和构造函数是未定义的。虽然我们确信这不会返回预期的结果

var n = arr.filter(Object.hasOwnProperty, "abc"); // [1, 2]

at least an error was not returned; let us continue

至少没有返回错误;让我们继续吧

var n = arr.filter(function(prop, val) {
          return prop.hasOwnProperty(this.valueOf())
        }, "abc"); // [Object abc: 123__proto__: Object]

the expected results are returned; though we are trying to use

返回预期结果;虽然我们正在尝试使用

var n = arr.filter(/* function reference */, this /* optional parameters passed */)

to

  1. filter an array for Object : {} objects; even if the object does not have a defined prototype or constructor; optionally converting JSON string "{"abc":123}" to object; though we have not reached this far, yet;

    过滤Object:{}对象的数组;即使对象没有定义的原型或构造函数;可选地将JSON字符串“{”abc“:123}”转换为对象;虽然我们还没到达这个目的,但是;

  2. pass a property name to .filter(callback, this) pattern where this serves as property name, or value of object; or utilize an approach using filter.bind , .call or .apply or other method to filter an object from the input array - without using full

    将属性名称传递给.filter(callback,this)模式,其中此属性作为属性名称或对象的值;或者使用filter.bind,.call或.apply或其他方法从输入数组中过滤对象 - 不使用完整

    .filter(function(prop, value) {})

    .filter(function(prop,value){})

    pattern. How can we coerce the Object.hasOwnProperty() call into a pattern similar to

    模式。我们如何将Object.hasOwnProperty()调用强制转换为类似于的模式

    .filter(Object.hasOwnProperty, "abc")

?

Mentioning .call, .bind and .apply after searching for a similar Question and finding JS Array.prototype.filter on prototype method . Though not certain how to implement approaches described in filtering both objects and objects having specific properties as described above.

在搜索类似的问题并在原型方法上找到JS Array.prototype.filter之后,提及.call,.bind和.apply。虽然不确定如何实现在过滤具有如上所述的特定属性的对象和对象中描述的方法。

Note, Question can also be resolved by a destructuring , or other es-6, es-7 approach, providing comparable or, even stricter results, when compared to .filter(). That is, use .filter() without

注意,问题还可以通过解构或其他es-6,es-7方法解决,与.filter()相比,提供可比较的甚至更严格的结果。也就是说,不使用.filter()

   function(prop, value) {

   }

pattern. Returning objects; that is Object , {} ; and objects filtered by property ; objects filtered by property value.

模式。归还对象;那是Object,{};和属性过滤的对象;按属性值过滤的对象。


Questions:

  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 ?

    如何在不使用匿名函数callbackpattern的情况下,在传递给Array.prototype.filter()的数组中使用或不使用Object原型或构造函数来过滤对象?

  2. How to filter specific objects within an array passed to Array.prototype.filter() by passing property name or value to match object without using anonymous function callback pattern ?

    如何通过将属性名称或值传递给匹配对象而不使用匿名函数回调模式来过滤传递给Array.prototype.filter()的数组中的特定对象?

6 个解决方案

#1


2  

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 ?

如何在不使用匿名函数callbackpattern的情况下,在传递给Array.prototype.filter()的数组中使用或不使用Object原型或构造函数来过滤对象?

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

callbackfn应该是一个接受三个参数的函数,并返回一个可以强制转换为布尔值true或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)

Number对象(函数的构造函数)确实返回NaN以进行错误的Number转换,但String和Object构造函数不返回false值(是的,filter(Number)也过滤掉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,

您可以创建客户功能OBJ,

function OBJ(value,index,arr){ return typeof value === "object" && !Array.isArray(value) }

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

或者在结果集中也欢迎使用Arrays,然后删除Array.isArray检查

function OBJ(value,index,arr){ return typeof value === "object" }

when used with

与...一起使用时

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

#2


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.

没有创建自己的功能,没有真正的安全方法。此外,它非常复杂,因为Object的定义过于宽泛。

Let's start with the following:

让我们从以下开始:

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

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 Array is an instance of Object? I am not sure as well.

你认为作为对象的null吗?我不这么认为。您是否将Array视为Object,因为Array是Object的实例?我也不确定。

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 Date Object 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.

这会从结果中排除null,但此处仍然存在数组。日期对象在这里以及具有任何原型的任何其他对象,例如new Boolean()也将是一个Object。此外,该对象可能被冻结,这也不会作为对象返回。

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.

因此,这两个示例都成功地证明了Object的定义过于宽泛,并且无法以有用的方式进行真正的处理。

#3


1  

You seem to want to filter an array for elements with a certain type. Pass an appropriate function to filter:

您似乎想要为具有特定类型的元素过滤数组。传递适当的功能来过滤:

array.filter(istype("String"))

You just need to write istype now:

你只需要立即编写istype:

function istype(type) {
  return function(x) {
    return Object.prototype.toString.call(x) === '[object ' + type + ']';
  }
}

You seem to have thought you could filter for numbers by saying filter(Number) etc. But that will not work. Number is just another function, which tries to turn something into a number (not check if it's a number). Then, filter filters the array depending on whether the result is truthy or falsy. Number will produce a truthy value for any non-zero number obviously, and true. For a string, or an object, or pretty much anything else, it will return NaN, which is falsy, with odd exceptions such as returning 0 for [] or an all-blank string.

您似乎认为可以通过说过滤器(数字)等来过滤数字。但这不起作用。 Number只是另一个函数,它试图将某些东西变成一个数字(不检查它是否是一个数字)。然后,根据结果是真实的还是假的,过滤器过滤数组。数字显然会产生任何非零数字的真值,并且为真。对于字符串,或对象,或几乎任何其他东西,它将返回NaN,这是假的,有奇怪的例外,例如为[]返回0或全空字符串。

Same with string. String is just another function, which tries to turn something into a string. Then, filter filters the array depending on whether the result is truthy or falsy. String will produce a truthy value for almost anything other than a non-empty string.

与字符串相同。 String只是另一个函数,它试图将某些东西变成一个字符串。然后,根据结果是真实的还是假的,过滤器过滤数组。 String将为除非空字符串之外的任何其他内容生成一个truthy值。

This has nothing whatsoever to do with destructuring; why would you think it does? You might want to remove that unfortunate part of your post. Nor is it clear what you mean by "calling filter without a callback"--using a callback to determine which elements to filter in and out is the entire DNA of filter. It is also unclear what pattern you are referring to when you say function(prop, value) { } pattern.

这与解构没有任何关系;为什么你会这么想?您可能想删除帖子中那个不幸的部分。 “没有回调调用过滤器”也不清楚你的意思 - 使用回调来确定过滤进出的元素是过滤器的整个DNA。当你说函数(prop,value){}模式时,你也不清楚你指的是什么模式。

At the end of your question, you ask two specific questions:

在问题的最后,您提出两个具体问题:

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 ?

如何在不使用匿名函数callbackpattern的情况下,在传递给Array.prototype.filter()的数组中使用或不使用Object原型或构造函数来过滤对象?

You filter objects from an input array by providing a function which determines if a particular element is an object. That is not what the object prototype or constructor Object is, so that won't help you. You have to write a little function to pass to filter, that's how it works. It could be anonymous, or it could be defined elsewhere and passed in

您可以通过提供确定特定元素是否为对象的函数来过滤输入数组中的对象。这不是对象原型或构造函数对象,因此对您没有帮助。你必须编写一个小函数来传递过滤器,这就是它的工作原理。它可以是匿名的,也可以在别处定义并传入

How to filter specific objects within an array passed to Array.prototype.filter() by passing property name or value to match object without using anonymous function callback pattern ?

如何通过将属性名称或值传递给匹配对象而不使用匿名函数回调模式来过滤传递给Array.prototype.filter()的数组中的特定对象?

What do you mean by "passing property name or value to match object"? Do you mean, filter out elements which are missing a particular property name or value? Then write a function to do that. There is no built-in function for this purpose, if that is what are looking for.

“将属性名称或值传递给匹配对象”是什么意思?您的意思是,过滤掉缺少特定属性名称或值的元素?然后编写一个函数来做到这一点。如果这是正在寻找的,那么没有用于此目的的内置功能。

#4


1  

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

在不传递回调函数的情况下,您可以使用RegExp.prototype.test方法传递正则表达式并绑定正则表达式

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.

这也会匹配包含[object Object]的任何字符串,但是字符串似乎不太可能包含那些确切的单词,除非你犯了一个错误并在数组中包含了字符串化的对象。

#5


1  

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

在ES6中,以下将针对您列出的示例值执行此操作:

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.

显然,这将通过调用Object.freeze,Object.seal或Object.preventExtensions来排除已标记为不可扩展的对象。除非您打算使用这些,否则我相信这样做。

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

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

console.log(objects);

#6


0  

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

到目前为止最接近的要求,也匹配Object.create(null)

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

#1


2  

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 ?

如何在不使用匿名函数callbackpattern的情况下,在传递给Array.prototype.filter()的数组中使用或不使用Object原型或构造函数来过滤对象?

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

callbackfn应该是一个接受三个参数的函数,并返回一个可以强制转换为布尔值true或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)

Number对象(函数的构造函数)确实返回NaN以进行错误的Number转换,但String和Object构造函数不返回false值(是的,filter(Number)也过滤掉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,

您可以创建客户功能OBJ,

function OBJ(value,index,arr){ return typeof value === "object" && !Array.isArray(value) }

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

或者在结果集中也欢迎使用Arrays,然后删除Array.isArray检查

function OBJ(value,index,arr){ return typeof value === "object" }

when used with

与...一起使用时

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

#2


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.

没有创建自己的功能,没有真正的安全方法。此外,它非常复杂,因为Object的定义过于宽泛。

Let's start with the following:

让我们从以下开始:

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

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 Array is an instance of Object? I am not sure as well.

你认为作为对象的null吗?我不这么认为。您是否将Array视为Object,因为Array是Object的实例?我也不确定。

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 Date Object 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.

这会从结果中排除null,但此处仍然存在数组。日期对象在这里以及具有任何原型的任何其他对象,例如new Boolean()也将是一个Object。此外,该对象可能被冻结,这也不会作为对象返回。

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.

因此,这两个示例都成功地证明了Object的定义过于宽泛,并且无法以有用的方式进行真正的处理。

#3


1  

You seem to want to filter an array for elements with a certain type. Pass an appropriate function to filter:

您似乎想要为具有特定类型的元素过滤数组。传递适当的功能来过滤:

array.filter(istype("String"))

You just need to write istype now:

你只需要立即编写istype:

function istype(type) {
  return function(x) {
    return Object.prototype.toString.call(x) === '[object ' + type + ']';
  }
}

You seem to have thought you could filter for numbers by saying filter(Number) etc. But that will not work. Number is just another function, which tries to turn something into a number (not check if it's a number). Then, filter filters the array depending on whether the result is truthy or falsy. Number will produce a truthy value for any non-zero number obviously, and true. For a string, or an object, or pretty much anything else, it will return NaN, which is falsy, with odd exceptions such as returning 0 for [] or an all-blank string.

您似乎认为可以通过说过滤器(数字)等来过滤数字。但这不起作用。 Number只是另一个函数,它试图将某些东西变成一个数字(不检查它是否是一个数字)。然后,根据结果是真实的还是假的,过滤器过滤数组。数字显然会产生任何非零数字的真值,并且为真。对于字符串,或对象,或几乎任何其他东西,它将返回NaN,这是假的,有奇怪的例外,例如为[]返回0或全空字符串。

Same with string. String is just another function, which tries to turn something into a string. Then, filter filters the array depending on whether the result is truthy or falsy. String will produce a truthy value for almost anything other than a non-empty string.

与字符串相同。 String只是另一个函数,它试图将某些东西变成一个字符串。然后,根据结果是真实的还是假的,过滤器过滤数组。 String将为除非空字符串之外的任何其他内容生成一个truthy值。

This has nothing whatsoever to do with destructuring; why would you think it does? You might want to remove that unfortunate part of your post. Nor is it clear what you mean by "calling filter without a callback"--using a callback to determine which elements to filter in and out is the entire DNA of filter. It is also unclear what pattern you are referring to when you say function(prop, value) { } pattern.

这与解构没有任何关系;为什么你会这么想?您可能想删除帖子中那个不幸的部分。 “没有回调调用过滤器”也不清楚你的意思 - 使用回调来确定过滤进出的元素是过滤器的整个DNA。当你说函数(prop,value){}模式时,你也不清楚你指的是什么模式。

At the end of your question, you ask two specific questions:

在问题的最后,您提出两个具体问题:

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 ?

如何在不使用匿名函数callbackpattern的情况下,在传递给Array.prototype.filter()的数组中使用或不使用Object原型或构造函数来过滤对象?

You filter objects from an input array by providing a function which determines if a particular element is an object. That is not what the object prototype or constructor Object is, so that won't help you. You have to write a little function to pass to filter, that's how it works. It could be anonymous, or it could be defined elsewhere and passed in

您可以通过提供确定特定元素是否为对象的函数来过滤输入数组中的对象。这不是对象原型或构造函数对象,因此对您没有帮助。你必须编写一个小函数来传递过滤器,这就是它的工作原理。它可以是匿名的,也可以在别处定义并传入

How to filter specific objects within an array passed to Array.prototype.filter() by passing property name or value to match object without using anonymous function callback pattern ?

如何通过将属性名称或值传递给匹配对象而不使用匿名函数回调模式来过滤传递给Array.prototype.filter()的数组中的特定对象?

What do you mean by "passing property name or value to match object"? Do you mean, filter out elements which are missing a particular property name or value? Then write a function to do that. There is no built-in function for this purpose, if that is what are looking for.

“将属性名称或值传递给匹配对象”是什么意思?您的意思是,过滤掉缺少特定属性名称或值的元素?然后编写一个函数来做到这一点。如果这是正在寻找的,那么没有用于此目的的内置功能。

#4


1  

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

在不传递回调函数的情况下,您可以使用RegExp.prototype.test方法传递正则表达式并绑定正则表达式

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.

这也会匹配包含[object Object]的任何字符串,但是字符串似乎不太可能包含那些确切的单词,除非你犯了一个错误并在数组中包含了字符串化的对象。

#5


1  

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

在ES6中,以下将针对您列出的示例值执行此操作:

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.

显然,这将通过调用Object.freeze,Object.seal或Object.preventExtensions来排除已标记为不可扩展的对象。除非您打算使用这些,否则我相信这样做。

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

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

console.log(objects);

#6


0  

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

到目前为止最接近的要求,也匹配Object.create(null)

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