Javascript 如何确定Javascript数组是否包含具有等于给定值的属性的对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8217419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to determine if Javascript array contains an object with an attribute that equals a given value?
提问by David Lozzi
I have an array like
我有一个像
vendors = [
{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
} //and so on goes array...
];
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 2015it is even simpler using the new arrow functions:
在ECMAScript 2015 中,使用新的箭头函数更加简单:
vendors.filter(vendor => vendor.Name === "Magenic")
采纳答案by Alex Turpin
2018 edit: This answer is from 2011, before browsers had widely supported array filtering methods and arrow functions. Have a look at CAFxX's answer.
2018 年编辑:这个答案来自 2011 年,在浏览器广泛支持数组过滤方法和箭头函数之前。看看CAFxX 的回答。
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;
}
}
回答by CAFxX
No need to reinvent the wheelloop, 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 */
}
回答by boxtrain
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:
这是您问题的最准确答案,即“检查是否存在某些内容”,暗示布尔结果。如果有任何“Magenic”对象,则为真,否则为假:
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.
如果您尝试将其强制转换为布尔值,它将不起作用,因为空数组(没有“Magenic”对象)仍然是真实的。所以只需magenicVendors.length
在您的条件中使用。
Array.prototype.find()
Array.prototype.find()
This will return the first 'Magenic' object (or undefined
if there aren't any):
这将返回第一个 'Magenic' 对象(或者undefined
如果没有):
let magenicVendor = vendors.find( vendor => vendor['Name'] === 'Magenic' );
This coerces to a boolean okay (any object is truthy, undefined
is falsy).
这会强制为布尔值 OK(任何对象都是真值,undefined
都是假值)。
Note: I'm using vendor["Name"] instead of vendor.Name because of the weird casing of the property names.
注意:我使用 vendor["Name"] 而不是 vendor.Name 因为属性名称的大小写很奇怪。
Note 2: No reason to use loose equality (==) instead of strict equality (===) when checking the name.
注 2:在检查名称时没有理由使用松散相等 (==) 而不是严格相等 (===)。
回答by TeaCoder
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.find][1]
来实现相同的效果。
Quoting MDN:
引用 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() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 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 i.e. `item` not boolean
}
See my jsfiddle linkThere is a polyfill for IE provided by mozilla
请参阅我的jsfiddle 链接Mozilla 提供了一个适用于 IE 的polyfill
回答by Mirza Leka
Here's the way I'd do it
这是我要做的方式
const found = vendors.some(item => item.Name === 'Magenic');
array.some()
method checks if there is at least one value in an array that matches criteria and returns a boolean.
From here on you can go with:
array.some()
方法检查数组中是否至少有一个值与条件匹配并返回一个布尔值。从这里开始,您可以使用:
if (found) {
// do something
} else {
// do something else
}
回答by Keith.Abramo
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)
你可以做的 if(vendors.Magnetic)
You will have to loop
你将不得不循环
回答by Lucas Bento
As per ECMAScript 6 specification, you can use findIndex
.
根据 ECMAScript 6 规范,您可以使用findIndex
.
const magenicIndex = vendors.findIndex(vendor => vendor.Name === 'Magenic');
const magenicIndex = vendors.findIndex(vendor => vendor.Name === 'Magenic');
magenicIndex
will hold either 0
(which is the index in the array) or -1
if it wasn't found.
magenicIndex
将保留0
(这是数组中的索引),或者-1
如果没有找到。
回答by Jay Chakra
As the OP has asked the question if the key exists or not.
由于 OP 已经询问了密钥是否存在的问题。
A more elegant solution that will return boolean using ES6 reduce function can be
使用 ES6 减少函数返回布尔值的更优雅的解决方案可以是
const magenicVendorExists = vendors.reduce((accumulator, vendor) => (accumulator||vendor.Name === "Magenic"), false);
Note:The initial parameter of reduce is a false
and if the array has the key it will return true.
注意:reduce 的初始参数是 a false
,如果数组有键,则返回 true。
Hope it helps for better and cleaner code implementation
希望它有助于更好和更清晰的代码实现
回答by jAndy
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.
然后你可以像查找哈希一样使用它。
vendors['Microsoft']; // 'DEF'
vendors['Apple']; // undefined
回答by Tomalak
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.jsto make this more pleasing:
当然,您可以使用linq.js 之类的库来使这更令人愉悦:
Enumerable.From(vendors).Where("$.Name == 'Magenic'").First();
(see jsFiddlefor 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 会比直接循环更快,但当事情变得更复杂时,它肯定会更灵活。