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

时间:2011-11-21 19:30:41

标签: javascript arrays

我有一个类似

的数组
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"));

26 个答案:

答案 0 :(得分:616)

无需重新发明 wheel 循环,至少不明确(使用arrow functionsmodern 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)

函数 mapfilterfind 和类似函数比简单循环慢得多。 对我来说,它们的可读性也低于简单循环,并且更难调试。使用它们看起来像是一种非理性的仪式。

最好有这样的东西:

 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并创建一个为我们做检查的函数。此功能的好处是,在检查了keyvalue的情况下,可以在整个项目中重用它来检查对象的任何数组。

足够的通话,让我们看看代码

数组

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提供了数组函数,使您可以相对轻松地实现此目的。它们是:

  1. Array.prototype.filter:采用回调函数作为测试,然后使用is回调对数组进行迭代,并根据此回调进行过滤。 返回一个新的过滤数组。
  2. 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))