找出JavaScript数组是否包含值的最简洁有效的方法是什么?

这是我知道的唯一方法:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
}

有没有更好、更简洁的方法来实现这一点?

这与堆栈溢出问题密切相关。在JavaScript数组中查找项目的最佳方法是什么?它解决了使用indexOf查找数组中的对象的问题。


当前回答

使用indexOf()

可以使用indexOf()方法检查数组中是否存在给定的值或元素。如果找到数组中元素的索引,indexOf()方法返回该元素的索引;如果找不到,则返回-1。让我们看一下以下示例:

var fruits=[“苹果”、“香蕉”、“芒果”、“橙子”、“木瓜”];var a=“芒果”;checkArray(a,水果);函数checkArray(a,fruits){//检查fruits数组中是否存在值如果(fruits.indexOf(a)!==-1) {return document.write(“true”);}其他{return document.write(“false”);}}

使用include()方法

ES6引入了includes()方法来非常容易地执行此任务。但是,此方法只返回true或false,而不返回索引号:

var fruits=[“苹果”、“香蕉”、“芒果”、“橙子”、“木瓜”];警报(水果,包括(“香蕉”));//输出:真警报(水果,包括(“椰子”));//输出:假警报(水果,包括(“橙色”));//输出:真警报(水果,包括(“樱桃”));//输出:假

如需进一步参考,请在此处结账

其他回答

希望更快的双向indexOf/lastIndexOf替代方案

2015

虽然新方法包含的内容非常好,但目前支持基本为零。

很长时间以来,我一直在想一种方法来替换缓慢的indexOf/lastIndexOf函数。

已经找到了一种表演方式,看看最热门的答案。我选择了@Damir Zekic发布的contains函数,这应该是最快的函数。但它也指出,基准是2008年的,因此已经过时。

我也更喜欢while而不是for,但不是出于特定原因,我用for循环结束了函数的编写。这也可以在一段时间内完成。

我很好奇,如果我在执行时检查数组的两侧,迭代是否会慢得多。显然没有,所以这个函数比排名靠前的函数快两倍左右。显然,它也比本地的更快。这是在一个真实的环境中,您永远不知道所搜索的值是在数组的开头还是结尾。

当你知道你只是用一个值推送一个数组时,使用lastIndexOf可能是最好的解决方案,但如果你必须遍历大数组,结果可能无处不在,这可能是一个让事情更快的可靠解决方案。

双向indexOf/lastIndexOf

function bidirectionalIndexOf(a, b, c, d, e){
  for(c=a.length,d=c*1; c--; ){
    if(a[c]==b) return c; //or this[c]===b
    if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
  }
  return -1
}

//Usage
bidirectionalIndexOf(array,'value');

性能测试

https://jsbench.me/7el1b8dj80

作为测试,我创建了一个包含100k个条目的数组。

三个查询:在数组的开头、中间和结尾。

我希望你也觉得这很有趣,并测试一下性能。

注意:正如您所看到的,我稍微修改了contains函数,以反映indexOf和lastIndexOf输出(因此,索引基本为true,-1为false)。这不应该伤害它。

阵列原型变体

Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
  for(c=this.length,d=c*1; c--; ){
    if(this[c]==b) return c; //or this[c]===b
    if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
  }
  return -1
},writable:false, enumerable:false});

// Usage
array.bidirectionalIndexOf('value');

该函数也可以很容易地修改为返回true或false,甚至返回对象、字符串或任何其他值。

下面是while变体:

function bidirectionalIndexOf(a, b, c, d){
  c=a.length; d=c-1;
  while(c--){
    if(b===a[c]) return c;
    if(b===a[d-c]) return d-c;
  }
  return c
}

// Usage
bidirectionalIndexOf(array,'value');

这怎么可能?

我认为,获取数组中反射索引的简单计算非常简单,比实际循环迭代快两倍。

这里有一个复杂的例子,每次迭代进行三次检查,但这仅在计算时间较长时才有可能,因为计算时间较长会导致代码速度减慢。

https://web.archive.org/web/20151019160219/http://jsperf.com/bidirectionalindexof/2

将唯一项目添加到其他列表

searchResults: [
                {
                    name: 'Hello',
                    artist: 'Selana',
                    album: 'Riga',
                    id: 1,
                },
                {
                    name: 'Hello;s',
                    artist: 'Selana G',
                    album: 'Riga1',
                    id: 2,
                },
                {
                    name: 'Hello2',
                    artist: 'Selana',
                    album: 'Riga11',
                    id: 3,
                }
            ],
            playlistTracks: [
              {
                name: 'Hello',
                artist: 'Mamunuus',
                album: 'Riga',
                id: 4,
              },
              {
                name: 'Hello;s',
                artist: 'Mamunuus G',
                album: 'Riga1',
                id: 2,
              },
              {
                name: 'Hello2',
                artist: 'Mamunuus New',
                album: 'Riga11',
                id: 3,
              }
            ],
            playlistName: "New PlayListTrack",
        };
    }

    // Adding an unique track in the playList
    addTrack = track => {
      if(playlistTracks.find(savedTrack => savedTrack.id === track.id)) {
        return;
      }
      playlistTracks.push(track);

      this.setState({
        playlistTracks
      })
    };

这绝不是最好的,但我只是在发挥创意,加入到曲目中。

不要使用此

Object.defineProperty(Array.prototype,“exists”{值:函数(元素,索引){var索引=索引||0返回索引==this.length-1:this[index]==元素?索引:this.exists(元素,++索引)}})//输出1console.log(['one','two'].exists('two'));//输出-1console.log(['one','two'].existes('tree'));console.log(['one','two','three','four'].exists('fur'));

很惊讶这个问题仍然没有添加最新的语法,增加了我的2美分。

假设我们有一个对象数组arrObj,我们想在其中搜索obj。

Array.prototype.indexOf->(返回索引或-1)通常用于查找数组中元素的索引。这也可用于搜索对象,但仅在传递对同一对象的引用时有效。

let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];


console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1

console.log([1, 3, 5, 2].indexOf(2)); //3

Array.prototype.includes->(返回true或false)

console.log(arrObj.includes(obj));  //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false

console.log([1, 3, 5, 2].includes(2)); //true

Array.prototype.find->(接受回调,返回CB中返回true的第一个值/对象)。

console.log(arrObj.find(e => e.age > 40));  //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }

console.log([1, 3, 5, 2].find(e => e > 2)); //3

Array.prototype.findIndex->(接受回调,返回CB中返回true的第一个值/对象的索引)。

console.log(arrObj.findIndex(e => e.age > 40));  //1
console.log(arrObj.findIndex(e => e.age > 40)); //1

console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1

由于find和findIndex需要回调,所以我们可以通过创造性地设置true条件从数组中获取任何对象(即使我们没有引用)。

检查数组JavaScript中是否存在值的最佳默认方法是some()

Array.prototype.some()

some()方法测试数组中是否至少有一个元素通过了所提供函数实现的测试。如果在数组中找到所提供的函数返回true的元素,则返回true;否则返回false。它不会修改数组。

const array = [1, 2, 3, 4, 5];

// checks whether an element is even
const even = (element) => element % 2 === 0;

console.log(array.some(even));
// expected output: true

some方法是浏览器兼容性中最好的方法

有关更多文档Array.prototype.some()-JavaScript | MDN

您还可以使用另外两个方法:find()和includes()。用这些方法你可以得到你的结果,但不是最好的。

Array.prototype.find()-JavaScript | MDN

Array.prototype.includes()-JavaScript | MDN