如何确定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; } });
现在,我用它顶部,因为它简单和自我解释的话。 谢谢。