我有一个数组

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

我如何检查这个数组,看看“Magenic”是否存在?我不想循环,除非迫不得已。我可能要处理几千条记录。


当前回答

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');

其他回答

你可以使用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);

希望我的回答能有所帮助。

除非你想这样重组:

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

你可以这样做如果(vendor . magnetic)

你必须循环

数组元素测试:

JS提供了数组函数,允许你相对容易地实现这一点。它们是:

array .prototype.filter:接受一个回调函数,这个回调函数是一个测试,然后数组被迭代,并根据这个回调进行过滤。返回一个新的过滤数组。 array .prototype.some:接受一个回调函数,它是一个测试,然后使用is callback迭代数组,如果任何元素通过测试,则返回布尔值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'); }

浏览器支持:

这两个函数都是ES6函数,不是所有浏览器都支持。为了克服这个问题,你可以使用填充剂。下面是Array.prototype.some(来自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; }; }

目前最简单的方法:

if (vendors.findIndex(item => item.Name == "Magenic") == -1) {
  //not found item
} else {
  //found item 
}

如果你正在使用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);
}