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

我有一个数组像

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

如何检查这个数组,看看Magenic是否存在? 我不想循环,除非必须。 我正在处理几千条logging。

更新

由于这是一个受欢迎的post,我以为我会分享我发现的新东西。 看来@CAFxX已经分享了! 我应该更经常阅读这些。 我遇到了https://benfrain.com/understanding-native-javascript-array-methods/ 。

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

使用ECMAScript 2015,使用新的箭头function甚至更简单:

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

没有“魔术”的方式来检查没有循环的数组中的某些东西。 即使你使用了一些函数,函数本身也会使用一个循环。 你可以做的就是一旦find你正在寻找的东西,就跳出循环,尽量减less计算时间。

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

没有必要重塑的 循环,至less不是明确的:

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

或者更好的是:

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

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

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

编辑:使用箭头function(只有现代浏览器)

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

被接受的答案仍然有效,但现在我们有一个ECMAScript 6原生方法[Array.find][1]来达到同样的效果。

引用MDN:

find()方法返回数组中第一个满足提供的testing函数的元素的值。 否则返回undefined。

 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 ie `item` not boolean } 

查看我的jsfiddle链接 Mozilla提供的 IE浏览器有一个polyfill

除非你想像这样重构它:

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

你可以做什么, if(vendors.Magnetic)

你将不得不循环

你不能没有真正看着对象。

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

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

那么你可以像查找哈希一样使用它。

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

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

Array.prototype.some()

这是你的问题最准确的答案,即“检查是否存在”,意味着一个布尔结果。 如果有任何“Magenic”对象,这将是真实的,否则为false:

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

Array.prototype.filter()

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

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

如果你试图强制这个布尔值,它将不起作用,作为一个空的数组(不'Magenic'对象)仍然是真的。 所以只要在条件中使用magenicVendors.length

Array.prototype.find()

这将返回第一个“Magenic”对象(如果undefined则为undefined ):

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

这迫使布尔值好(任何对象是truthy, undefined是falsy)。


注意:由于属性名称的怪异shell,我正在使用vendor [“Name”]而不是vendor.Name。

注2:检查名称时,没有理由使用松散相等(==)而不是严格相等(===)。

按照ECMAScript 6规范,你可以使用findIndex

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

magenicIndex将保存0 (它是数组中的索引),如果没有find则为-1

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

 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]; } } } 

当然,你可以使用像linq.js这样的库来使这个更令人愉快:

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

(请参阅jsFiddle进行演示)

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

如果你正在使用jQuery,你可以利用grep来创build包含所有匹配对象的数组:

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

然后使用结果数组:

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

我宁愿去正则expression式。

如果你的代码如下,

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

我会推荐

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

纠正我,如果我错了..我可以使用forEach方法,

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

现在,我用它顶部,因为它简单和自我解释的话。 谢谢。