如何确定Javascript数组是否包含一个属性等于给定值的对象?

时间:2022-12-15 15:59:47

I have an array like

我有一个数组

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    } and so on... 
];

How do I check this array to see if Magenic exists? I don't want to loop, unless I have to. I'm working with potentially a couple thousand records.

如何检查这个数组以查看Magenic是否存在?我不想循环,除非我必须这么做。我可能要处理几千条记录。

UPDATED

更新

Since this has been a popular post, I thought I'd share something new I found. And it appears @CAFxX has already shared this! I should read these more often. I came across https://benfrain.com/understanding-native-javascript-array-methods/.

由于这是一个很受欢迎的帖子,我想分享一些我发现的新东西。看来@CAFxX已经分享了!我应该多读一些。我遇到了https://benfrain.com/understanding-native-javascript-array-methods/。

vendors.filter(function(vendor){ return vendor.Name === "Magenic" });

And with ECMAScript 2015 it is even simpler using the new arrow functions:

使用ECMAScript 2015,使用新的箭头功能更简单:

vendors.filter(vendor => (vendor.Name === "Magenic"));

14 个解决方案

#1


153  

There is no "magic" way to check for something in an array without a loop. Even if you use some function, the function itself will use a loop. What you can do is break out of the loop as soon as you find what you're looking for to minimize computational time.

没有一种“神奇”的方法来检查数组中没有循环的内容。即使你使用某个函数,函数本身也会使用一个循环。你所能做的就是一旦你找到了你想要的东西就跳出这个循环来最小化计算时间。

var found = false;
for(var i = 0; i < vendors.length; i++) {
    if (vendors[i].Name == 'Magenic') {
        found = true;
        break;
    }
}

#2


330  

No need to reinvent the wheel loop, at least not explicitly (using arrow functions, modern browsers only):

不需要重新创建*循环,至少不需要显式地(仅使用箭头函数,仅使用现代浏览器):

if (vendors.filter(e => e.name === 'Magenic').length > 0) {
  /* vendors contains the element we're looking for */
}

or, better yet:

或者,更好的是:

if (vendors.some(e => e.name === 'Magenic')) {
  /* vendors contains the element we're looking for */
}

EDIT: If you need compatibility with lousy browsers then your best bet is:

编辑:如果你需要与糟糕的浏览器兼容,那么你最好的选择是:

if (vendors.filter(function(e) { return e.name === 'Magenic'; }).length > 0) {
  /* vendors contains the element we're looking for */
}

#3


35  

The accepted answer still works but now we have an ECMAScript 6 native method [Array.find][1] to achieve the same effect.

接受的答案仍然有效,但是现在我们有了ECMAScript 6本机方法[Array]。找到][1]达到同样的效果。

Quoting MDN:

引用中数:

The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.

find()方法返回数组中满足所提供的测试函数的第一个元素的值。否则将返回未定义。

var arr = []; 
var item = {
  id: '21',
  step: 'step2',
  label: 'Banana',
  price: '19$'
};

arr.push(item);
/* note : data is the actual object that matched search criteria 
  or undefined if nothing matched */
var data = arr.find( function( ele ) { 
    return ele.id === '21';
} );

if( data ) {
 console.log( 'found' );
 console.log(data); // This is entire object i.e. `item` not boolean
}

See my jsfiddle link There is a polyfill for IE provided by mozilla

看看我的jsfiddle链接,mozilla为IE提供了一个polyfill

#4


28  

No loop necessary. Three methods that come to mind:

没有必要循环。我想到了三种方法:

Array.prototype.some()

Array.prototype.some()

This is the most exact answer for your question, i.e. "check if something exists", implying a bool result. This will be true if there are any 'Magenic' objects, false otherwise:

这是对你的问题最准确的答案,也就是。“检查某物是否存在”,意味着bool结果。如果有“魔法”对象,则为真,否则为假:

let hasMagenicVendor = vendors.some( vendor => vendor['Name'] === 'Magenic' )

Array.prototype.filter()

Array.prototype.filter()

This will return an array of all 'Magenic' objects, even if there is only one (will return a one-element array):

这将返回所有“Magenic”对象的数组,即使只有一个(将返回一个单元素数组):

let magenicVendors = vendors.filter( vendor => vendor['Name'] === 'Magenic' )

If you try to coerce this to a boolean, it will not work, as an empty array (no 'Magenic' objects) is still truthy. So just use magenicVendors.length in your conditional.

如果您试图将此强制转换为一个布尔值,那么它将不会起作用,因为一个空数组(没有“mag”对象)仍然是真实的。所以用magenicVendors。长在你的条件。

Array.prototype.find()

Array.prototype.find()

This will return the first 'Magenic' object (or undefined if there aren't any):

这将返回第一个“Magenic”对象(如果没有定义,则未定义):

let magenicVendor = vendors.find( vendor => vendor['Name'] === 'Magenic' );

This coerces to a boolean okay (any object is truthy, undefined is falsy).

这强制到布尔值(任何对象都是真实的,未定义的都是假的)。


Note: I'm using vendor["Name"] instead of vendor.Name because of the weird casing of the property names.

注意:我使用的是供应商["Name"]而不是供应商。名称是由于属性名称的奇怪外壳。

Note 2: No reason to use loose equality (==) instead of strict equality (===) when checking the name.

注意2:在检查名称时,没有理由使用宽松的等号(=)代替严格的等号(=== =)。

#5


16  

Unless you want to restructure it like this:

除非你想这样重组:

vendors = {
    Magenic: {
      Name: 'Magenic',
      ID: 'ABC'
     },
    Microsoft: {
      Name: 'Microsoft',
      ID: 'DEF'
    } and so on... 
};

to which you can do if(vendors.Magnetic)

如果(供应商。磁性)

You will have to loop

你必须循环。

#6


14  

As per ECMAScript 6 specification, you can use findIndex.

根据ECMAScript 6规范,您可以使用findIndex。

const magenicIndex = vendors.findIndex(vendor => vendor.Name === 'Magenic');

const magenicIndex =供应商。findIndex(供应商= >供应商。Name = = = ' Magenic ');

magenicIndex will hold either 0 (which is the index in the array) or -1 if it wasn't found.

如果没有找到,magenicIndex将保存0(数组中的索引)或-1。

#7


13  

You cannot without looking into the object really.

你不能不仔细观察这个物体。

You probably should change your structure a little, like

你可能应该稍微改变一下你的结构

vendors = {
    Magenic:   'ABC',
    Microsoft: 'DEF'
};

Then you can just use it like a lookup-hash.

然后可以像使用lookup-hash一样使用它。

vendors['Microsoft']; // 'DEF'
vendors['Apple']; // undefined

#8


4  

You have to loop, there is no way around it.

你必须循环,没有办法绕过它。

function seekVendor(vendors, name) {
  for (var i=0, l=vendors.length; i<l; i++) {
    if (typeof vendors[i] == "object" && vendors[i].Name === name) {
      return vendors[i];
    }
  }
}

Of course you could use a library like linq.js to make this more pleasing:

当然,您可以使用linq这样的库。为了使这更令人愉快:

Enumerable.From(vendors).Where("$.Name == 'Magenic'").First();

(see jsFiddle for a demo)

(参见jsFiddle获得演示)

I doubt that linq.js will be faster than a straight-forward loop, but it certainly is more flexible when things get a little more complicated.

我怀疑linq。js将比直接循环要快,但当事情变得更复杂时,它肯定更灵活。

#9


3  

if you're using jquery you can take advantage of grep to create array with all matching objects:

如果您使用jquery,可以利用grep创建具有所有匹配对象的数组:

var results = $.grep(vendors, function (e) {
    return e.Name == "Magenic";
});

and then use the results array:

然后使用结果数组:

for (var i=0, l=results.length; i<l; i++) {
    console.log(results[i].ID);
}

#10


1  

You can use lodash. If lodash library is too heavy for your application consider chunking out unnecessary function not used.

您可以使用lodash。如果lodash库对应用程序来说太重,可以考虑将不必要的功能分段使用。

let newArray = filter(_this.props.ArrayOne, function(item) {
                    return find(_this.props.ArrayTwo, {"speciesId": item.speciesId});
                });

This is just one way to do this. Another one can be:

这只是一种方法。另一个可以:

var newArray=  [];
     _.filter(ArrayOne, function(item) {
                        return AllSpecies.forEach(function(cItem){
                            if (cItem.speciesId == item.speciesId){
                            newArray.push(item);
                          }
                        }) 
                    });

console.log(arr);

console.log(arr);

The above example can also be rewritten without using any libraries like:

上面的例子也可以重写,无需使用任何库,比如:

var newArray=  [];
ArrayOne.filter(function(item) {
                return ArrayTwo.forEach(function(cItem){
                    if (cItem.speciesId == item.speciesId){
                    newArray.push(item);
                  }
                }) 
            });
console.log(arr);

Hope my answer helps.

希望我的回答有帮助。

#11


0  

Correct me if i'm wrong.. i could have used forEach method like this,

如果我错了请纠正我。我可以用这种方法,

var found=false;
vendors.forEach(function(item){
   if(item.name === "name"){
       found=true;
       return;
   }
});

Nowadays i'm used to it ,because of it simplicity and self explanatory word. Thank you.

现在我已经习惯了,因为它的简单和自解释的词。谢谢你!

#12


0  

Alternatively you can do:

或者你能做什么:

const find = (key, needle) => return !!~vendors.findIndex(v => (v[key] === needle));

#13


0  

var without2 = (arr, args) => arr.filter(v => v.id !== args.id); Example:

var without2 = (arr, args) => arr。过滤器(v = >。id ! = = args.id);例子:

without2([{id:1},{id:1},{id:2}],{id:2})

without2([{ id:1 },{ id:1 },{ id:2 }),{ id:2 })

Result: without2([{id:1},{id:1},{id:2}],{id:2})

结果:without2([{ id:1 },{ id:1 },{ id:2 }),{ id:2 })

#14


-1  

I would rather go with regex.

我宁愿选择regex。

If your code is as follows,

如果您的代码如下所示,

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    }
];

I would recommend

我建议

/"Name":"Magenic"/.test(JSON.stringify(vendors))

#1


153  

There is no "magic" way to check for something in an array without a loop. Even if you use some function, the function itself will use a loop. What you can do is break out of the loop as soon as you find what you're looking for to minimize computational time.

没有一种“神奇”的方法来检查数组中没有循环的内容。即使你使用某个函数,函数本身也会使用一个循环。你所能做的就是一旦你找到了你想要的东西就跳出这个循环来最小化计算时间。

var found = false;
for(var i = 0; i < vendors.length; i++) {
    if (vendors[i].Name == 'Magenic') {
        found = true;
        break;
    }
}

#2


330  

No need to reinvent the wheel loop, at least not explicitly (using arrow functions, modern browsers only):

不需要重新创建*循环,至少不需要显式地(仅使用箭头函数,仅使用现代浏览器):

if (vendors.filter(e => e.name === 'Magenic').length > 0) {
  /* vendors contains the element we're looking for */
}

or, better yet:

或者,更好的是:

if (vendors.some(e => e.name === 'Magenic')) {
  /* vendors contains the element we're looking for */
}

EDIT: If you need compatibility with lousy browsers then your best bet is:

编辑:如果你需要与糟糕的浏览器兼容,那么你最好的选择是:

if (vendors.filter(function(e) { return e.name === 'Magenic'; }).length > 0) {
  /* vendors contains the element we're looking for */
}

#3


35  

The accepted answer still works but now we have an ECMAScript 6 native method [Array.find][1] to achieve the same effect.

接受的答案仍然有效,但是现在我们有了ECMAScript 6本机方法[Array]。找到][1]达到同样的效果。

Quoting MDN:

引用中数:

The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.

find()方法返回数组中满足所提供的测试函数的第一个元素的值。否则将返回未定义。

var arr = []; 
var item = {
  id: '21',
  step: 'step2',
  label: 'Banana',
  price: '19$'
};

arr.push(item);
/* note : data is the actual object that matched search criteria 
  or undefined if nothing matched */
var data = arr.find( function( ele ) { 
    return ele.id === '21';
} );

if( data ) {
 console.log( 'found' );
 console.log(data); // This is entire object i.e. `item` not boolean
}

See my jsfiddle link There is a polyfill for IE provided by mozilla

看看我的jsfiddle链接,mozilla为IE提供了一个polyfill

#4


28  

No loop necessary. Three methods that come to mind:

没有必要循环。我想到了三种方法:

Array.prototype.some()

Array.prototype.some()

This is the most exact answer for your question, i.e. "check if something exists", implying a bool result. This will be true if there are any 'Magenic' objects, false otherwise:

这是对你的问题最准确的答案,也就是。“检查某物是否存在”,意味着bool结果。如果有“魔法”对象,则为真,否则为假:

let hasMagenicVendor = vendors.some( vendor => vendor['Name'] === 'Magenic' )

Array.prototype.filter()

Array.prototype.filter()

This will return an array of all 'Magenic' objects, even if there is only one (will return a one-element array):

这将返回所有“Magenic”对象的数组,即使只有一个(将返回一个单元素数组):

let magenicVendors = vendors.filter( vendor => vendor['Name'] === 'Magenic' )

If you try to coerce this to a boolean, it will not work, as an empty array (no 'Magenic' objects) is still truthy. So just use magenicVendors.length in your conditional.

如果您试图将此强制转换为一个布尔值,那么它将不会起作用,因为一个空数组(没有“mag”对象)仍然是真实的。所以用magenicVendors。长在你的条件。

Array.prototype.find()

Array.prototype.find()

This will return the first 'Magenic' object (or undefined if there aren't any):

这将返回第一个“Magenic”对象(如果没有定义,则未定义):

let magenicVendor = vendors.find( vendor => vendor['Name'] === 'Magenic' );

This coerces to a boolean okay (any object is truthy, undefined is falsy).

这强制到布尔值(任何对象都是真实的,未定义的都是假的)。


Note: I'm using vendor["Name"] instead of vendor.Name because of the weird casing of the property names.

注意:我使用的是供应商["Name"]而不是供应商。名称是由于属性名称的奇怪外壳。

Note 2: No reason to use loose equality (==) instead of strict equality (===) when checking the name.

注意2:在检查名称时,没有理由使用宽松的等号(=)代替严格的等号(=== =)。

#5


16  

Unless you want to restructure it like this:

除非你想这样重组:

vendors = {
    Magenic: {
      Name: 'Magenic',
      ID: 'ABC'
     },
    Microsoft: {
      Name: 'Microsoft',
      ID: 'DEF'
    } and so on... 
};

to which you can do if(vendors.Magnetic)

如果(供应商。磁性)

You will have to loop

你必须循环。

#6


14  

As per ECMAScript 6 specification, you can use findIndex.

根据ECMAScript 6规范,您可以使用findIndex。

const magenicIndex = vendors.findIndex(vendor => vendor.Name === 'Magenic');

const magenicIndex =供应商。findIndex(供应商= >供应商。Name = = = ' Magenic ');

magenicIndex will hold either 0 (which is the index in the array) or -1 if it wasn't found.

如果没有找到,magenicIndex将保存0(数组中的索引)或-1。

#7


13  

You cannot without looking into the object really.

你不能不仔细观察这个物体。

You probably should change your structure a little, like

你可能应该稍微改变一下你的结构

vendors = {
    Magenic:   'ABC',
    Microsoft: 'DEF'
};

Then you can just use it like a lookup-hash.

然后可以像使用lookup-hash一样使用它。

vendors['Microsoft']; // 'DEF'
vendors['Apple']; // undefined

#8


4  

You have to loop, there is no way around it.

你必须循环,没有办法绕过它。

function seekVendor(vendors, name) {
  for (var i=0, l=vendors.length; i<l; i++) {
    if (typeof vendors[i] == "object" && vendors[i].Name === name) {
      return vendors[i];
    }
  }
}

Of course you could use a library like linq.js to make this more pleasing:

当然,您可以使用linq这样的库。为了使这更令人愉快:

Enumerable.From(vendors).Where("$.Name == 'Magenic'").First();

(see jsFiddle for a demo)

(参见jsFiddle获得演示)

I doubt that linq.js will be faster than a straight-forward loop, but it certainly is more flexible when things get a little more complicated.

我怀疑linq。js将比直接循环要快,但当事情变得更复杂时,它肯定更灵活。

#9


3  

if you're using jquery you can take advantage of grep to create array with all matching objects:

如果您使用jquery,可以利用grep创建具有所有匹配对象的数组:

var results = $.grep(vendors, function (e) {
    return e.Name == "Magenic";
});

and then use the results array:

然后使用结果数组:

for (var i=0, l=results.length; i<l; i++) {
    console.log(results[i].ID);
}

#10


1  

You can use lodash. If lodash library is too heavy for your application consider chunking out unnecessary function not used.

您可以使用lodash。如果lodash库对应用程序来说太重,可以考虑将不必要的功能分段使用。

let newArray = filter(_this.props.ArrayOne, function(item) {
                    return find(_this.props.ArrayTwo, {"speciesId": item.speciesId});
                });

This is just one way to do this. Another one can be:

这只是一种方法。另一个可以:

var newArray=  [];
     _.filter(ArrayOne, function(item) {
                        return AllSpecies.forEach(function(cItem){
                            if (cItem.speciesId == item.speciesId){
                            newArray.push(item);
                          }
                        }) 
                    });

console.log(arr);

console.log(arr);

The above example can also be rewritten without using any libraries like:

上面的例子也可以重写,无需使用任何库,比如:

var newArray=  [];
ArrayOne.filter(function(item) {
                return ArrayTwo.forEach(function(cItem){
                    if (cItem.speciesId == item.speciesId){
                    newArray.push(item);
                  }
                }) 
            });
console.log(arr);

Hope my answer helps.

希望我的回答有帮助。

#11


0  

Correct me if i'm wrong.. i could have used forEach method like this,

如果我错了请纠正我。我可以用这种方法,

var found=false;
vendors.forEach(function(item){
   if(item.name === "name"){
       found=true;
       return;
   }
});

Nowadays i'm used to it ,because of it simplicity and self explanatory word. Thank you.

现在我已经习惯了,因为它的简单和自解释的词。谢谢你!

#12


0  

Alternatively you can do:

或者你能做什么:

const find = (key, needle) => return !!~vendors.findIndex(v => (v[key] === needle));

#13


0  

var without2 = (arr, args) => arr.filter(v => v.id !== args.id); Example:

var without2 = (arr, args) => arr。过滤器(v = >。id ! = = args.id);例子:

without2([{id:1},{id:1},{id:2}],{id:2})

without2([{ id:1 },{ id:1 },{ id:2 }),{ id:2 })

Result: without2([{id:1},{id:1},{id:2}],{id:2})

结果:without2([{ id:1 },{ id:1 },{ id:2 }),{ id:2 })

#14


-1  

I would rather go with regex.

我宁愿选择regex。

If your code is as follows,

如果您的代码如下所示,

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    }
];

I would recommend

我建议

/"Name":"Magenic"/.test(JSON.stringify(vendors))