我有一个类似
的数组vendors = [
{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
} //and so on goes array...
];
如何检查此数组以查看Magenic是否存在?我不想循环,除非我必须。我正在处理几千条记录。
已更新
由于这是一篇很受欢迎的帖子,我想我会分享一些我发现的新内容。似乎@CAFxX已经分享了这个!我应该经常阅读这些内容。我遇到了https://benfrain.com/understanding-native-javascript-array-methods/。
vendors.filter(function(vendor){ return vendor.Name === "Magenic" });
使用ECMAScript 2015,使用新的箭头功能更简单:
vendors.filter(vendor => (vendor.Name === "Magenic"));
答案 0 :(得分:616)
无需重新发明 wheel 循环,至少不明确(使用arrow functions,modern browsers only):
if (vendors.filter(e => e.Name === 'Magenic').length > 0) {
/* vendors contains the element we're looking for */
}
或,更好:
if (vendors.some(e => e.Name === 'Magenic')) {
/* vendors contains the element we're looking for */
}
编辑:如果您需要与糟糕的浏览器兼容,那么最好的选择是:
if (vendors.filter(function(e) { return e.Name === 'Magenic'; }).length > 0) {
/* vendors contains the element we're looking for */
}
答案 1 :(得分:209)
2018年编辑:这个答案来自2011年,之前浏览器广泛支持数组过滤方法和箭头功能。看看CAFxX's answer。
在没有循环的情况下,没有“神奇”的方法来检查数组中的某些内容。即使你使用某个函数,函数本身也会使用循环。你可以做的就是在找到你想要的东西时尽快摆脱循环,以最大限度地缩短计算时间。
var found = false;
for(var i = 0; i < vendors.length; i++) {
if (vendors[i].Name == 'Magenic') {
found = true;
break;
}
}
答案 2 :(得分:52)
无需循环。想到三种方法:
<强> Array.prototype.some()强>
这是您问题的最准确答案,即&#34;检查某些内容是否存在&#34;,暗示一个bool结果。如果有任何&#39; Magenic&#39;对象,否则为false:
let hasMagenicVendor = vendors.some( vendor => vendor['Name'] === 'Magenic' )
<强> Array.prototype.filter()强>
这将返回所有&#39; Magenic&#39;对象,即使只有一个(将返回一个单元素数组):
let magenicVendors = vendors.filter( vendor => vendor['Name'] === 'Magenic' )
如果你试图将它强制转换为布尔值,它将无法工作,因为一个空数组(没有&#39; Magenic&#39;对象)仍然是真实的。所以只需在条件中使用magenicVendors.length
。
<强> Array.prototype.find()强>
这将返回第一个&#39; Magenic&#39;对象(或undefined
如果没有):
let magenicVendor = vendors.find( vendor => vendor['Name'] === 'Magenic' );
这会强制转换为布尔值(任何对象都是真实的,undefined
是假的)。
注意:由于属性名称的奇怪外壳,我使用供应商[&#34;名称&#34;]而不是vendor.Name。
注2:检查名称时,没有理由使用松散等式(==)而不是严格相等(===)。
答案 3 :(得分:39)
接受的答案仍然有效但现在我们有一个ECMAScript 6原生方法[Array.find][1]
来达到同样的效果。
引用MDN:
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
}
查看我的jsfiddle link IE provided by mozilla
有一个填充答案 4 :(得分:18)
除非你想像这样重组:
vendors = {
Magenic: {
Name: 'Magenic',
ID: 'ABC'
},
Microsoft: {
Name: 'Microsoft',
ID: 'DEF'
} and so on...
};
您可以if(vendors.Magnetic)
你必须循环
答案 5 :(得分:18)
根据ECMAScript 6规范,您可以使用findIndex
。
import asyncio
async def run_spider():
while True:
sp = await asyncio.subprocess.create_subprocess_shell(
"scrapy srawl presentcodespider -o ../static/presentcodes.new.json",
cwd="./presentcodeSpider")
code = await sp.wait()
if code != 0:
print("Warning: something went wrong, code %d" % code)
continue # retry immediately
if os.path.exists("/static/presentcodes.new.json"):
# output was created, overwrite older version (if any)
os.rename("/static/presentcodes.new.json", "/static/presentcodes.json")
else:
print("Warning: output file was not found")
await asyncio.sleep(20)
const magenicIndex = vendors.findIndex(vendor => vendor.Name === 'Magenic');
将保留magenicIndex
(数组中的索引)或0
,如果找不到。
答案 6 :(得分:14)
这就是我要做的方式
class MainWindow(Gtk.Window):
def _init_(self)
self.builder = Gtk.Builder()
self.builder.add_from_file("mygladefile.glade")
self.window = self.builder.get_object('main_window')
self.window.fullscreen()
const found = vendors.some(item => item.Name === 'Magenic');
方法检查数组中是否至少有一个与条件匹配的值并返回一个布尔值。
从这里开始,您可以使用:
array.some()
答案 7 :(得分:13)
你真的不能不看对象。
你可能应该稍微改变你的结构,比如
vendors = {
Magenic: 'ABC',
Microsoft: 'DEF'
};
然后你可以像查询哈希一样使用它。
vendors['Microsoft']; // 'DEF'
vendors['Apple']; // undefined
答案 8 :(得分:9)
OP询问了密钥是否存在的问题。
可以使用ES6 reduce函数返回布尔值的更优雅的解决方案是
const magenicVendorExists = vendors.reduce(vendor => (vendor.Name === "Magenic"), false);
注意:reduce的初始参数是false
,如果数组具有键,它将返回true。
希望它有助于更好,更干净地执行代码
答案 9 :(得分:4)
你必须循环,没有办法解决它。
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会比直接循环更快,但是当事情变得更复杂时,它肯定会更灵活。
答案 10 :(得分:4)
如果你正在使用jquery,你可以利用grep来创建包含所有匹配对象的数组:
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);
}
答案 11 :(得分:3)
const check = vendors.find((item)=>item.Name==='Magenic')
console.log(check)
尝试此代码。
如果存在该项或元素,则输出将向您显示该元素。如果不存在,则输出将为“未定义”。
答案 12 :(得分:3)
您可以为我尝试一下。
const _ = require('lodash');
var arr = [
{
name: 'Jack',
id: 1
},
{
name: 'Gabriel',
id: 2
},
{
name: 'John',
id: 3
}
]
function findValue(arr,value) {
return _.filter(arr, function (object) {
return object['name'].toLowerCase().indexOf(value.toLowerCase()) >= 0;
});
}
console.log(findValue(arr,'jack'))
//[ { name: 'Jack', id: 1 } ]
答案 13 :(得分:2)
const VENDORS = [{ Name: 'Magenic', ID: 'ABC' }, { Name: 'Microsoft', ID: 'DEF' }];
console.log(_.some(VENDORS, ['Name', 'Magenic']));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>
答案 14 :(得分:1)
函数 map
、filter
、find
和类似函数比简单循环慢得多。
对我来说,它们的可读性也低于简单循环,并且更难调试。使用它们看起来像是一种非理性的仪式。
最好有这样的东西:
arrayHelper = {
arrayContainsObject: function (array, object, key){
for (let i = 0; i < array.length; i++){
if (object[key] === array[i][key]){
return true;
}
}
return false;
}
};
并在给定的 OP 示例中像这样使用它:
vendors = [{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
}
];
let abcObject = {ID: 'ABC', Name: 'Magenic'};
let isContainObject = arrayHelper.arrayContainsObject(vendors, abcObject, 'ID');
答案 15 :(得分:1)
可能为时已晚,但是javascript数组具有一个返回布尔值的every
方法。
vendors.every( vendor => vendor['Name'] !== 'Magenic' )
答案 16 :(得分:1)
为了比较一个对象和另一个对象,我将for循环(用于循环遍历对象)和some()组合在一起。 您不必担心数组越界越好,这样可以节省一些代码。有关.some的文档,请参见here
var productList = [{id: 'text3'}, {id: 'text2'}, {id: 'text4', product: 'Shampoo'}]; // Example of selected products
var theDatabaseList = [{id: 'text1'}, {id: 'text2'},{id: 'text3'},{id:'text4', product: 'shampoo'}];
var objectsFound = [];
for(let objectNumber in productList){
var currentId = productList[objectNumber].id;
if (theDatabaseList.some(obj => obj.id === currentId)) {
// Do what you need to do with the matching value here
objectsFound.push(currentId);
}
}
console.log(objectsFound);
我将一个对象与另一个对象进行比较的另一种方法是使用带有Object.keys()。length的嵌套for循环来获取数组中对象的数量。下面的代码:
var productList = [{id: 'text3'}, {id: 'text2'}, {id: 'text4', product: 'Shampoo'}]; // Example of selected products
var theDatabaseList = [{id: 'text1'}, {id: 'text2'},{id: 'text3'},{id:'text4', product: 'shampoo'}];
var objectsFound = [];
for(var i = 0; i < Object.keys(productList).length; i++){
for(var j = 0; j < Object.keys(theDatabaseList).length; j++){
if(productList[i].id === theDatabaseList[j].id){
objectsFound.push(productList[i].id);
}
}
}
console.log(objectsFound);
要回答您的确切问题,如果只是在对象中搜索值,则可以在循环中使用单个。
var vendors = [
{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
}
];
for(var ojectNumbers in vendors){
if(vendors[ojectNumbers].Name === 'Magenic'){
console.log('object contains Magenic');
}
}
答案 17 :(得分:1)
您可以使用 lodash 。如果lodash库对于您的应用程序而言太重,请考虑将未使用的不必要函数分块。
let newArray = filter(_this.props.ArrayOne, function(item) {
return find(_this.props.ArrayTwo, {"speciesId": item.speciesId});
});
这只是一种方法。另一个可以是:
var newArray= [];
_.filter(ArrayOne, function(item) {
return AllSpecies.forEach(function(cItem){
if (cItem.speciesId == item.speciesId){
newArray.push(item);
}
})
});
console.log(arr);
上述示例也可以重写,而不使用任何库,如:
var newArray= [];
ArrayOne.filter(function(item) {
return ArrayTwo.forEach(function(cItem){
if (cItem.speciesId == item.speciesId){
newArray.push(item);
}
})
});
console.log(arr);
希望我的回答有所帮助。
答案 18 :(得分:1)
如果我错了,请纠正我。
我可以使用forEach
这样的方法,
var found=false;
vendors.forEach(function(item){
if(item.name === "name"){
found=true;
return;
}
});
现在我已经习惯了它,因为它简单易懂。 谢谢。
答案 19 :(得分:0)
这里的许多答案很好,也很容易。但是,如果您的对象数组具有一组固定的值,则可以使用以下技巧:
将所有名称映射到一个对象中。
vendors = [
{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
}
];
var dirtyObj = {}
for(var count=0;count<vendors.length;count++){
dirtyObj[vendors[count].Name] = true //or assign which gives you true.
}
现在,这个dirtyObj可以一次又一次地使用,而不会出现任何循环。
if(dirtyObj[vendor.Name]){
console.log("Hey! I am available.");
}
答案 20 :(得分:0)
我解决此问题的方法是使用ES6并创建一个为我们做检查的函数。此功能的好处是,在检查了key
和value
的情况下,可以在整个项目中重用它来检查对象的任何数组。
足够的通话,让我们看看代码
数组
const ceos = [
{
name: "Jeff Bezos",
company: "Amazon"
},
{
name: "Mark Zuckerberg",
company: "Facebook"
},
{
name: "Tim Cook",
company: "Apple"
}
];
功能
const arrayIncludesInObj = (arr, key, valueToCheck) => {
let found = false;
arr.some(value => {
if (value[key] === valueToCheck) {
found = true;
return true; // this will break the loop once found
}
});
return found;
}
通话/使用情况
const found = arrayIncludesInObj(ceos, "name", "Tim Cook"); // true
const found = arrayIncludesInObj(ceos, "name", "Tim Bezos"); // false
答案 21 :(得分:0)
var without2 = (arr, args) => arr.filter(v => v.id !== args.id);
例如:
without2([{id:1},{id:1},{id:2}],{id:2})
结果: without2([{ID:1},{ID:1},{ID:2}],{ID:2})
答案 22 :(得分:0)
JS提供了数组函数,使您可以相对轻松地实现此目的。它们是:
Array.prototype.filter
:采用回调函数作为测试,然后使用is回调对数组进行迭代,并根据此回调进行过滤。 返回一个新的过滤数组。 Array.prototype.some
:采用回调函数作为测试,然后使用is回调迭代数组,并如果任何元素通过了测试, 返回布尔值true 。否则返回false 最好通过一个例子来解释具体细节:
vendors = [
{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
} //and so on goes array...
];
// filter returns a new array, we instantly check if the length
// is longer than zero of this newly created array
if (vendors.filter(company => company.Name === 'Magenic').length ) {
console.log('I contain Magenic');
}
// some would be a better option then filter since it directly returns a boolean
if (vendors.some(company => company.Name === 'Magenic')) {
console.log('I also contain Magenic');
}
这2个函数是ES6
函数,并非所有浏览器都支持它们。为了克服这个问题,您可以使用polyfill。这是Array.prototype.some
的polyfill(来自MDN):
if (!Array.prototype.some) {
Array.prototype.some = function(fun, thisArg) {
'use strict';
if (this == null) {
throw new TypeError('Array.prototype.some called on null or undefined');
}
if (typeof fun !== 'function') {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
for (var i = 0; i < len; i++) {
if (i in t && fun.call(thisArg, t[i], i, t)) {
return true;
}
}
return false;
};
}
答案 23 :(得分:0)
或者你可以这样做:
function destroyer(arr) {
var args = Array.prototype.slice.call(arguments); //turns arguments into arrays
function checkArgs() {
for (var i = 0; i < arr.length; i++) {
for (var j = 1; j < args.length; j++) {
if (arr[i] == args[j]) {
delete arr[i];
}
}
}
return arr;
}
return arr.filter(checkArgs);
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
答案 24 :(得分:0)
const a = [{one:2},{two:2},{two:4}]
const b = a.filter(val => "two" in val).length;
if (b) {
...
}
答案 25 :(得分:-4)
我宁愿选择正则表达式。
如果您的代码如下,
vendors = [
{
Name: 'Magenic',
ID: 'ABC'
},
{
Name: 'Microsoft',
ID: 'DEF'
}
];
我会推荐
/"Name":"Magenic"/.test(JSON.stringify(vendors))