Je dois déterminer si une valeur existe dans un tableau.
J'utilise la fonction suivante:
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] == obj) {
return true;
}
}
return false;
}
La fonction ci-dessus renvoie toujours false.
Les valeurs de tableau et l'appel de fonction sont les suivants:
arrValues = ["Sam","Great", "Sample", "High"]
alert(arrValues.contains("Sam"));
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;
};
Vous pouvez l'utiliser comme ceci:
var myArray = [0,1,2],
needle = 1,
index = contains.call(myArray, needle); // true
jQuery a une fonction utilitaire pour cela:
$.inArray(value, array)
Renvoie l'indice de value
dans array
. Renvoie -1
si array
ne contient pas value
.
Voir aussi Comment puis-je vérifier si un tableau inclut un objet en JavaScript?
C’est généralement le but de la méthode indexOf (). Tu dirais:
return arrValues.indexOf('Sam') > -1
Dans ES2016, il y a Array.prototype.includes()
.
La méthode
includes()
détermine si un tableau inclut un élément donné, en retournanttrue
oufalse
selon le cas.
_["Sam", "Great", "Sample", "High"].includes("Sam"); // true
_
Selon kangax et MDN , les plates-formes suivantes sont prises en charge:
La prise en charge peut être étendue avec Babel (avec _babel-polyfill
_) ou core-js
. MDN fournit également un polyfill :
_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;
};
}
_
Il est presque toujours plus sûr d'utiliser une bibliothèque telle que lodash simplement à cause de tous les problèmes de compatibilité et d'efficacité entre navigateurs.
Efficacité, car vous pouvez être assuré qu’à tout moment, une bibliothèque très populaire telle que le soulignement aura la méthode la plus efficace pour accomplir une fonction utilitaire comme celle-ci.
_.includes([1, 2, 3], 3); // returns true
Si vous êtes préoccupé par le volume ajouté à votre application en incluant toute la bibliothèque, sachez que vous pouvez inclure des fonctionnalités séparément:
var includes = require('lodash/collections/includes');
AVIS: Avec les anciennes versions de lodash, il s'agissait de _.contains()
plutôt que de _.includes()
.
tl; dr
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;
}
Exemple
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>
Réponse plus longue
Je sais que cette question ne concerne pas vraiment l'extension des objets intégrés, mais la tentative du PO et les commentaires sur cette réponse soulignent ce débat. Mon commentaire du 12 février 2013 mentionne un article qui décrit très bien ce débat, mais ce lien a été rompu et je ne peux pas modifier le commentaire original car il s'est écoulé trop de temps. Je l'inclue donc ici .
Si vous cherchez à étendre l'objet Array
intégré avec une méthode contains
, la meilleure façon de procéder consiste probablement à utiliser ce polyfill à partir de MDN . (Voir aussi la section this de l'article de MDN sur l'héritage prototypique, qui explique que "La seule bonne raison d'étendre un prototype intégré est de prendre en charge les fonctionnalités du code JavaScript plus récent. moteurs, par exemple Array.forEach, etc. ")
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;
};
}
Vous ne voulez pas une égalité stricte ou vous voulez choisir?
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;
}
Depuis ECMAScript6, on peut utiliser Set
:
var myArray = ['A', 'B', 'C'];
var mySet = new Set(myArray);
var hasB = mySet.has('B'); // true
var hasZ = mySet.has('Z'); // false
Ma petite contribution:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
//usage
if(isInArray(my_array, "my_value"))
{
//...
}
Si vous avez accès à ECMA 5, vous pouvez utiliser la méthode some .
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;
Si vous avez accès à ECMA 6, vous pouvez utiliser la méthode inclut .
arrValues = ["Sam","Great", "Sample", "High"];
arrValues.includes('Sam');
=> true;
Étant donné l'implémentation de indexOf pour IE (comme décrit par eyelidless):
Array.prototype.contains = function(obj) {
return this.indexOf(obj) > -1;
};
Vous pouvez utiliser méthode _. IndexOf ou si vous ne souhaitez pas inclure la totalité de la bibliothèque Underscore.js dans votre application, vous pouvez consulter comment ils l'ont fait et extraire code nécessaire.
_.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;
};
Une autre option consisterait à utiliser Array.some
( si disponible ) de la manière suivante:
Array.prototype.contains = function(obj) {
return this.some( function(e){ return e === obj } );
}
La fonction anonyme transmise à Array.some
renverra true
si et seulement si le tableau contient un élément identique à obj
. En l'absence d'un tel élément, la fonction ne renverra pas true
pour aucun des éléments du tableau, donc Array.some
retournera également false
.
Wow, il y a beaucoup de bonnes réponses à cette question.
Je n'en ai pas vu qui adopte une approche reduce
alors je vais l'ajouter dans:
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);
La réponse fournie n'a pas fonctionné pour moi, mais elle m'a donné une idée:
Array.prototype.contains = function(obj)
{
return (this.join(',')).indexOf(obj) > -1;
}
Ce n'est pas parfait parce que les éléments qui sont identiques au-delà des groupes peuvent finir par correspondre. Comme mon exemple
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);
}
Lorsque j'appelle cette fonction avec les champs 'g' et 'h' contenant respectivement 1 et 2, elle le trouve toujours car la chaîne résultante de la jointure est la suivante: 1,1,2,2,3,3
Comme il est douteux dans ma situation que je rencontre ce type de situation, je l'utilise. Je pensais que je partagerais au cas où quelqu'un d'autre ne pourrait pas faire fonctionner la réponse choisie non plus.
L'utilisation de la fonction tableau .map qui exécute une fonction pour chaque valeur d'un tableau me semble la plus propre.
Cette méthode peut fonctionner aussi bien pour les tableaux simples que pour les tableaux d'objets où vous devez voir si une clé/valeur existe dans un tableau d'objets.
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
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;
}
Ce programme vérifie si l'élément donné est trouvé ou non. Id text1 représente l'identifiant de la zone de texte et searchele représente l'élément à rechercher (obtenu par l'utilisateur); si vous voulez indexer, utilisez i value
La solution la plus simple pour une fonction contains
serait une fonction qui ressemble à ceci:
var contains = function (haystack, needle) {
return !!~haystack.indexOf(needle);
}
Idéalement, vous ne feriez pas de cette fonction une fonction autonome, mais une partie d'une bibliothèque d'aide:
var helper = {};
helper.array = {
contains : function (haystack, needle) {
return !!~haystack.indexOf(needle);
},
...
};
Maintenant, si vous faites partie de ces malchanceux qui ont encore besoin de supporter IE <9 et ne peuvent donc pas compter sur indexOf
, vous pouvez utiliser ceci polyfill , ce que j'ai obtenu - du MDN :
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;
};
}