题 确定数组是否包含值[duplicate]


这个问题在这里已有答案:

我需要确定数组中是否存在值。

我使用以下功能:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] == obj) {
            return true;
        }
    }
    return false;
}

上面的函数总是返回false。

数组值和函数调用如下:

arrValues = ["Sam","Great", "Sample", "High"]
alert(arrValues.contains("Sam"));

1152
2017-07-25 08:18


起源


该代码适用于Safari 4.0.2。顺便说一句:我会做的 === 比较而不仅仅是 ==。 - Georg Schölly
“上述函数总是返回false。”不,它没有:该功能按预期工作 - 错误必须在其他地方。 - Christoph
也可以看看: stackoverflow.com/q/237104/1569 - Factor Mystic
Finally its worked. its due to improper trim of the comparing value. there was some space in the comparing value (来自提问者的评论,到了 接受了答案。) - ANeves
它有效,你应该使用 === 代替 == - hellol11


答案:


var contains = function(needle) {
    // Per spec, the way to identify NaN is that it is not equal to itself
    var findNaN = needle !== needle;
    var indexOf;

    if(!findNaN && typeof Array.prototype.indexOf === 'function') {
        indexOf = Array.prototype.indexOf;
    } else {
        indexOf = function(needle) {
            var i = -1, index = -1;

            for(i = 0; i < this.length; i++) {
                var item = this[i];

                if((findNaN && item !== item) || item === needle) {
                    index = i;
                    break;
                }
            }

            return index;
        };
    }

    return indexOf.call(this, needle) > -1;
};

你可以像这样使用它:

var myArray = [0,1,2],
    needle = 1,
    index = contains.call(myArray, needle); // true

CodePen验证/使用


949
2017-07-25 08:22



请注意,数组上的indexOf未在IE中实现,但您可以自己定义它 - RaYell
你应该使用类型比较 === 与本机实现兼容 - Christoph
修正了比较并添加了缺失 return -1;请注意,根据ES5规范,在有符号的零和NaN的情况下,此方法的行为将与原生方法不同(见15.4.4.14和9.12对11.9.6) - Christoph
这个答案指的是什么版本的IE? - Daniel Allen Langdon
@RiceFlourCookies,IE <9。 - eyelidlessness


jQuery的 有一个实用功能:

$.inArray(value, array)

返回索引 value 在 array。返回 -1 如果 array 不含 value

也可以看看 如何检查数组是否包含JavaScript中的对象?


929
2017-09-24 19:34



不要让“inArray”这个名字欺骗你。如上所述(但当然我没有仔细阅读),返回-1 (不是假的) 如果元素不存在。 - Greg Bernhardt
我无法相信他们的功能如此糟糕。 - Stephen Paul
@Steve Paul名字有什么问题?它做了它所说的:-1 =它不存在,其他任何东西=它就在那里 - Jeffz
'inArray'意味着将返回一个布尔值,指示是否可以在数组中找到该元素。因此,用户可能会想要使用表达式:if($ .inArray('myval',myarray)){...}如果'myval'不在myarray中,这将评估为true。此外,如果myval的索引为0,它将评估为false。 - Stephen Paul
非布尔值 $.inArray回归肯定是jQuery的一个错误。当然,它应该重命名为 $.indexOf,如果这是它的填充功能? - ChaseMoskal


这通常是indexOf()方法的用途。你会说:

return arrValues.indexOf('Sam') > -1

746
2017-07-25 08:25



indexOf 在<IE9中不起作用。 - Doug S
不适用 NaN - Trevor
我喜欢Kenneth J的评论比答案更多的赞成。但好东西 - 我已经将indexOf()用于字符串,但我不知道你可以将它用于数组。 - doubleDown
return ~arrValues.indexOf('Sam') 将返回 false 如果元素不存在于数组中 - Zychoo
@SebastianMach,如果所有网络开发人员都采取立场说不...用户将被迫改变。并且帮助公司省钱,因为他们不必雇佣IE开发人员 - Sujay Phadke


Array.prototype.includes()

在ES2016中,有 Array.prototype.includes()

includes() 方法确定数组是否包含某个元素,返回 true 要么 false 作为适当的。

["Sam", "Great", "Sample", "High"].includes("Sam"); // true

支持

根据 kangax 和 MDN,支持以下平台:

  • Chrome 47
  • 边缘14
  • Firefox 43
  • 歌剧34
  • Safari 9
  • 节点6

可以使用扩展支持 巴别塔 (使用 babel-polyfill) 要么 core-js。 MDN还提供了一个 填充工具

if (![].includes) {
  Array.prototype.includes = function(searchElement /*, fromIndex*/ ) {
    'use strict';
    var O = Object(this);
    var len = parseInt(O.length) || 0;
    if (len === 0) {
      return false;
    }
    var n = parseInt(arguments[1]) || 0;
    var k;
    if (n >= 0) {
      k = n;
    } else {
      k = len + n;
      if (k < 0) {k = 0;}
    }
    var currentElement;
    while (k < len) {
      currentElement = O[k];
      if (searchElement === currentElement ||
         (searchElement !== searchElement && currentElement !== currentElement)) {
        return true;
      }
      k++;
    }
    return false;
  };
}

247
2018-06-09 06:45



我很想在几个关于多个变量值或数组的javascript问题中发布这个答案。来自MDN的polyfill非常好。 - Nathan Goings
谢谢你! Babel polyfils很好:-)我记得2年前jQuery在任何项目中,现在它是Babel :) JavaScript社区的大赢家!在许多平台上已经有了ES7可用的表格,包括babel pollyfils kangax.github.io/compat-table/es2016plus - Lukas
应该是公认的答案 - Antoine


使用像这样的库几乎总是更安全 lodash 仅仅因为跨浏览器兼容性和效率的所有问题。

效率是因为可以保证在任何给定时间,像下划线这样非常受欢迎的库将具有完成这样的实用功能的最有效方法。

_.includes([1, 2, 3], 3); // returns true

如果您担心通过包含整个库而添加到应用程序中的批量,请知道您可以单独包含功能:

var includes = require('lodash/collections/includes');

注意: 对于旧版本的lodash,这是 _.contains() 而不是 _.includes()


116
2018-01-25 03:00



@threed,您不必包含整个库。部分功能可以包含在require('lodash / collections / contains')中。 - ncabral
仅供参考:现在是lodash 4 _.includes() 代替 _.contains()。 - shadowhorst
谢谢@shadowhorst。我编辑了答案以反映这一点。 - ncabral
辅助库看起来很方便,但往往会经常改变,请参阅上面的评论“lodash 4”.contains()'现在'.includes()'” - anneb
@anneb可以说任何图书馆。这就是为什么你有semver和依赖管理。 - ncabral


TL;博士 

function includes(k) {
  for(var i=0; i < this.length; i++){
    if( this[i] === k || ( this[i] !== this[i] && k !== k ) ){
      return true;
    }
  }
  return false;
}

function includes(k) {
  for(var i=0; i < this.length; i++){
    if( this[i] === k || ( this[i] !== this[i] && k !== k ) ){
      return true;
    }
  }
  return false;
}

function log(msg){
  $('#out').append('<div>' + msg + '</div>');  
}

var arr = [1, "2", NaN, true];
arr.includes = includes;

log('var arr = [1, "2", NaN, true];');
log('<br/>');
log('arr.includes(1): ' + arr.includes(1));
log('arr.includes(2): ' + arr.includes(2));
log('arr.includes("2"): ' + arr.includes("2"));
log('arr.includes(NaN): ' + arr.includes(NaN));
log('arr.includes(true): ' + arr.includes(true));
log('arr.includes(false): ' + arr.includes(false));
#out{
  font-family:monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=out></div>

更长的答案

我知道这个问题并不是关于是否扩展内置对象,但是OP的尝试和对这个答案的评论突出了这个争论。我从2013年2月12日发表的评论引用了一篇文章,该文章非常清楚地概述了这一争论,但是这个链接破了,我无法编辑原始评论,因为时间太长了,所以我把它包括在内 这里

如果你想扩展内置 Array 用一个对象 contains 方法,可能最好和最负责任的方法是使用这个polyfill MDN。 (也可以看看 这个 关于原型继承的MDN文章的一节,解释了这一点 “扩展内置原型的唯一理由是向后移植新JavaScript引擎的功能;例如Array.forEach等。”

if (!Array.prototype.includes) {
  Array.prototype.includes = function(searchElement /*, fromIndex*/ ) {
    'use strict';
    var O = Object(this);
    var len = parseInt(O.length) || 0;
    if (len === 0) {
      return false;
    }
    var n = parseInt(arguments[1]) || 0;
    var k;
    if (n >= 0) {
      k = n;
    } else {
      k = len + n;
      if (k < 0) {k = 0;}
    }
    var currentElement;
    while (k < len) {
      currentElement = O[k];
      if (searchElement === currentElement ||
         (searchElement !== searchElement && currentElement !== currentElement)) {
        return true;
      }
      k++;
    }
    return false;
  };
}

不想要严格平等,还是想选择?

function includes(k, strict) {
  strict = strict !== false; // default is true
  // strict = !!strict; // default is false
  for(var i=0; i < this.length; i++){
    if( (this[i] === k && strict) || 
        (this[i] == k && !strict) ||
        (this[i] !== this[i] && k !== k)
    ) {
      return true;
    }
  }
  return false;
}

46
2017-09-15 20:03



这种增加内置类型的技术不是不受欢迎吗? - Sahat Yalkabov
越野车: [1,2,4].contains([].contains) 是真的。由于同样的错误也不必要地慢。避免for..in over arrays。 - Eamon Nerbonne
@Eamon Nerbonne:我刚刚将这些代码粘贴到jsfiddle.net并得到了错误。难道我做错了什么。另外,你能详细说明这个bug如何减慢代码的速度吗?最后,我不知道“for..in”循环有性能差异。你可以向我解释或指导一篇文章,我可以阅读更多内容吗? - Trevor
@threed完全不真实:“这是一种非常常见的做法,并被jQuery广泛使用” - 他们为他们使用的一些对象创建新的原型,但不修改内置原型 - naugtur


从ECMAScript6开始,人们可以使用 Set

var myArray = ['A', 'B', 'C'];
var mySet = new Set(myArray);
var hasB = mySet.has('B'); // true
var hasZ = mySet.has('Z'); // false

33
2018-01-07 13:05





我的小贡献:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

//usage
if(isInArray(my_array, "my_value"))
{
    //...
}

18
2017-09-13 17:29





鉴于IE的indexOf的实现(如eyelidlessness所述):

Array.prototype.contains = function(obj) {
    return this.indexOf(obj) > -1;
};

17
2017-07-25 09:12



那是多余的。 - eyelidlessness
也许,但它会使你的代码更清晰。 if(myArray.contains(obj))更易于阅读,并且比if(myArray.indexOf(obj)> -1)更好地陈述意图。我绝对会实现这两个目标。 - rlovtang
这适用于所有浏览器吗?或者某些浏览器认为索引“2”和2相同? - Trevor