web-dev-qa-db-fra.com

Déterminer si un tableau contient une valeur

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"));
1283
Prasad
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

validation/utilisation CodePen

995
eyelidlessness

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?

983
codeape

C’est généralement le but de la méthode indexOf (). Tu dirais:

return arrValues.indexOf('Sam') > -1
861
Gabriel Hurley

Array.prototype.includes ()

Dans ES2016, il y a Array.prototype.includes() .

La méthode includes() détermine si un tableau inclut un élément donné, en retournant true ou false selon le cas.

Exemple

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

Soutien

Selon kangax et MDN , les plates-formes suivantes sont prises en charge:

  • Chrome 47
  • Edge 14
  • Firefox 43
  • Opéra 34
  • Safari 9
  • Noeud 6

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;
  };
}
_
348
Dale

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().

130
ncabral

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;
}
46
Trevor

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
42
Nicolas

Ma petite contribution:

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

//usage
if(isInArray(my_array, "my_value"))
{
    //...
}
21
Matías Cánepa

Si vous avez accès à ECMA 5, vous pouvez utiliser la méthode some .

Lien de méthode MDN 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 .

MDN INCLUDES Method Link

arrValues = ["Sam","Great", "Sample", "High"];

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

Étant donné l'implémentation de indexOf pour IE (comme décrit par eyelidless):

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

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;
  };
11
Wojciech Bednarski

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.

9
Hunan Rostomyan

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

en voici un violon en action .

7
Chris Schmitz

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.

5
Kakoroat

L'utilisation de la fonction tableau .map qui exécute une fonction pour chaque valeur d'un tableau me semble la plus propre.

Réf: Array.prototype.map ()

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
4
Ian Vasquez
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

2
deeban

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;
  };
}
1
John Slegers