关于Javascript:确定一个数组中包含一个值

Determine whether an array contains a value

本问题已经有最佳答案,请猛点这里访问。

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

我使用以下功能:

1
2
3
4
5
6
7
8
9
Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] == obj) {
            return true;
        }
    }
    return false;
}

上面的函数总是返回false。

数组值和函数调用如下:

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
};

您可以这样使用它:

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

代码笔验证/使用


jquery有一个实用程序函数:

1
$.inArray(value, array)

返回arrayvalue的索引。如果array不包含value则返回-1

另请参见如何检查数组是否在javascript中包含对象?


这通常是indexof()方法的作用。你会说:

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


array.prototype.includes()。

ES2016年有Array.prototype.includes()

The includes() method determines whether an array includes a certain element, returning true or false as appropriate.

例子

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

支持

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

  • 铬47
  • 边缘14
  • 火狐43
  • 歌剧34
  • 狩猎9
  • 节点6

可以使用babel(使用babel-polyfillcore-js扩展支持。MDN还提供polyfill:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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;
  };
}


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

效率,因为你可以保证,在任何给定的时间,一个非常流行的图书馆,如下划线将有最有效的方法来实现这样的效用函数。

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

如果您担心通过将整个库添加到应用程序中的大容量,则知道您可以单独包括功能:

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

注意:对于旧版本的LoaSH,这是EDOCX1×7,而不是EDCOX1×8。


DR

1
2
3
4
5
6
7
8
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;
}

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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('' + msg + '');  
}

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));
1
2
3
#out{
  font-family:monospace;
}
1
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">

更长的答案

我知道这个问题实际上不是关于是否扩展内置对象,但是OP的尝试和对这个答案的评论突出了这一争论。我在2013年2月12日发表的评论引用了一篇文章,该文章非常好地概述了这场辩论,但是链接断了,我无法编辑最初的评论,因为时间太长了,所以我将其包含在这里。

如果您希望使用contains方法扩展内置的array对象,那么最好和最负责任的方法可能是使用MDN中的这个polyfill。(另请参见有关原型继承的MDN文章的这一部分,该部分解释了"扩展内置原型的唯一好理由是将较新的javascript引擎的功能(例如array.foreach等)进行反向移植")。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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;
  };
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}


由于ecmascript6,可以使用Set

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

我的小小贡献:

1
2
3
4
5
6
7
8
9
10
function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

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

鉴于IE指数的实现(如无眼睑所述):

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


如果您可以访问ECMA 5,可以使用某些方法。

MDN某些方法链接

1
2
3
4
5
6
7
8
9
10
11
12
13
arrValues = ["Sam","Great","Sample","High"];

function namePresent(name){
  return name === this.toString();
}
// Note:
// namePresent requires .toString() method to coerce primitive value
// i.e. String {0:"S", 1:"a", 2:"m", length: 3, [[PrimitiveValue]]:"Sam"}
// into
//"Sam"

arrValues.some(namePresent, 'Sam');
=> true;

如果您有权访问ECMA 6,则可以使用include方法。

MDN包含方法链接

1
2
3
4
arrValues = ["Sam","Great","Sample","High"];

arrValues.includes('Sam');
=> true;

你可以使用indexof方法,或者如果你不想在你的应用程序中包含整个underline.js库,你可以看看他们是怎么做的,并提取必要的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    _.indexOf = function(array, item, isSorted) {
    if (array == null) return -1;
    var i = 0, l = array.length;
    if (isSorted) {
      if (typeof isSorted == 'number') {
        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
      } else {
        i = _.sortedIndex(array, item);
        return array[i] === item ? i : -1;
      }
    }
    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
    for (; i < l; i++) if (array[i] === item) return i;
    return -1;
  };


另一种选择是按以下方式使用Array.some(如有):

1
2
3
Array.prototype.contains = function(obj) {
  return this.some( function(e){ return e === obj } );
}

传递给Array.some的匿名函数将返回true,前提是数组中有一个元素与obj相同。如果没有这样的元素,函数将不会为数组的任何元素返回true,因此Array.some也将返回false


哇,这个问题有很多很好的答案。

我没有看到一个采用reduce方法的,所以我将它添加到:

1
2
3
4
5
6
7
var searchForValue = 'pig';

var valueIsInArray = ['horse', 'cat', 'dog'].reduce(function(previous, current){
    return previous || searchForValue === current ? true : false;
}, false);

console.log('The value"' + searchForValue + '" is in the array: ' + valueIsInArray);

这里有一把小提琴。


使用array.map函数为数组中的每个值执行一个函数对我来说似乎是最干净的。

参考:array.prototype.map()

这个方法既适用于简单数组,也适用于需要查看键/值是否存在于对象数组中的对象数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function inArray(myArray,myValue){
    var inArray = false;
    myArray.map(function(key){
        if (key === myValue){
            inArray=true;
        }
    });
    return inArray;
};

var anArray = [2,4,6,8]
console.log(inArray(anArray, 8)); // returns true
console.log(inArray(anArray, 1)); // returns false

function inArrayOfObjects(myArray,myValue,objElement){
    var inArray = false;
    myArray.map(function(arrayObj){
        if (arrayObj[objElement] === myValue) {
            inArray=true;
        }
    });
    return inArray;
};

var objArray = [{id:4,value:'foo'},{id:5,value:'bar'}]
console.log(inArrayOfObjects(objArray, 4, 'id')); // returns true
console.log(inArrayOfObjects(objArray, 'bar', 'value')); // returns true
console.log(inArrayOfObjects(objArray, 1, 'id')); // returns false

提供的答案对我不起作用,但它给了我一个想法:

1
2
3
4
Array.prototype.contains = function(obj)
    {
        return (this.join(',')).indexOf(obj) > -1;
    }

这并不完美,因为分组之外相同的项目最终可能会匹配。比如我的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var c=[];
var d=[];
function a()
{
    var e = '1';
    var f = '2';
    c[0] = ['1','1'];
    c[1] = ['2','2'];
    c[2] = ['3','3'];
    d[0] = [document.getElementById('g').value,document.getElementById('h').value];

    document.getElementById('i').value = c.join(',');
    document.getElementById('j').value = d.join(',');
    document.getElementById('b').value = c.contains(d);
}

当我使用分别包含1和2的"g"和"h"字段调用此函数时,它仍然会找到它,因为从联接得到的字符串是:1,1,2,2,3,3

因为在我的情况下,我会遇到这种情况,这是值得怀疑的,我正在使用这种情况。我想我会分享,以防其他人也不能使选择的答案起作用。


1
2
3
4
5
6
7
8
9
10
11
12
function setFound(){  
 var l = arr.length, textBox1 = document.getElementById("text1");
    for(var i=0; i<l;i++)
    {
     if(arr[i]==searchele){
      textBox1 .value ="Found";
      return;
     }
    }
    textBox1 .value ="Not Found";
return;
}

This program checks whether the given element is found or not. Id
text1 represents id of textbox and searchele represents element to be
searched (got fron user); if you want index, use i value


对于contains函数,最简单的解决方案是如下所示的函数:

1
2
3
var contains = function (haystack, needle) {
    return !!~haystack.indexOf(needle);
}

理想情况下,您不会将其设置为一个独立的函数,而是助手库的一部分:

1
2
3
4
5
6
7
8
var helper = {};

helper.array = {
    contains : function (haystack, needle) {
        return !!~haystack.indexOf(needle);
    },
    ...
};

现在,如果你碰巧是那些不走运的人,他们仍然需要支持IE<9,因此不能依赖于indexOf,你可以使用这个polyfill,这是我从MDN得到的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(searchElement, fromIndex) {
    var k;
    if (this == null) {
      throw new TypeError('"this" is null or not defined');
    }
    var o = Object(this);
    var len = o.length >>> 0;
    if (len === 0) {
      return -1;
    }
    var n = +fromIndex || 0;

    if (Math.abs(n) === Infinity) {
      n = 0;
    }
    if (n >= len) {
      return -1;
    }
    k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
    while (k < len) {
      if (k in o && o[k] === searchElement) {
        return k;
      }
      k++;
    }
    return -1;
  };
}

我喜欢简单:

1
2
var days = [1, 2, 3, 4, 5];
if ( 2 in days ) {console.log('weekday');}