Vérifiez si toutes les valeurs du tableau sont égales

190

J'ai besoin de trouver des tableaux où toutes les valeurs sont égales. Quel est le moyen le plus rapide de faire cela? Dois-je le parcourir et comparer simplement les valeurs?

['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false
Marvin3
la source
1
@TJCrowder Je parie que vous réfléchissez déjà à la meilleure solution;)
VisioN
2
@TJCrowder: Sans parler de la volonté des demandeurs d'accepter réellement les réponses. Les utilisateurs avec 1 représentant semblent souvent être des types de demande et d'exécution qui partent dès qu'ils ont une réponse copiable-collable, ces derniers temps.
Cerbrus
1
Quelque chose autour de cette approche devrait fonctionner? a.join(',').split(a[0]).length === a.length + 1
Jashwant
1
@ TomášZato: "OP" signifie "affiche originale" (la personne qui pose la question).
TJ Crowder

Réponses:

290
const allEqual = arr => arr.every( v => v === arr[0] )
allEqual( [1,1,1,1] )  // true

Ou one-liner:

[1,1,1,1].every( (val, i, arr) => val === arr[0] )   // true

Array.prototype.every (de MDN): la every()méthode teste si tous les éléments du tableau passent le test implémenté par la fonction fournie.

Golopot
la source
12
La brièveté est l'âme de l'esprit
svarog
1
J'ai créé un cas jsperf . Cette méthode surpasse la plupart des candidats.
Junliang Huang
1
const everythings_equal = array => array.every(thing => thing === array[0]);
Константин Ван
8
Utilisez au somelieu de every: arr.some( v => v !== arr[0] ). Cela reviendra tôt lorsque le premier élément trouvé est différent de arr[0].
janvier
2
@Jan everyfait également un retour anticipé.
golopot
111

Edit: Soyez un ninja rouge:

!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });

Résultats:

var array = ["a", "a", "a"] => result: "true"
var array = ["a", "b", "a"] => result: "false"
var array = ["false", ""] => result: "false"
var array = ["false", false] => result: "false"
var array = ["false", "false"] => result: "true"
var array = [NaN, NaN] => result: "false" 

Avertissement:

var array = [] => result: TypeError thrown

C'est parce que nous ne transmettons pas une valeur initiale . Donc, vous voudrez peut-être vérifier d' array.lengthabord.

Martin
la source
5
peut être un peu en retard à la fête ... je pense que cela ne fonctionne pas si votre tableau est fait de falses! par exemple try [false, false, false] .reduce (function (a, b) {return (a === b)? a: false;});
George Flourentzos
3
@Martin: ["false", ""]retourne true: /
dalgard
6
Cela peut être pris d'un cran en utilisant NaN. Puisque les deux NaN === NaNet NaN !== NaNsont faux, cela garantit qu'une fois que le prevest défini sur NaN, aucune valeur ne peut le supprimer. L'ajout d'une double négation convertit également les résultats en trueet false, puisque NaNc'est faux. Forme finale:!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
Filipe Silva
3
DOWNVOTED . Et si les éléments sont égaux mais faux ?
Константин Ван
3
J'ai voté contre parce que cela ne fonctionne pas avec les valeurs booléennes.
Tyguy7
62

Cela marche. Vous créez une méthode sur Array à l'aide de prototype.

if (Array.prototype.allValuesSame === undefined) {
  Array.prototype.allValuesSame = function() {
    for (let i = 1; i < this.length; i++) {
      if (this[i] !== this[0]) {
        return false;
      }
    }
    return true;
  }
}

Appelez cela de cette façon:

let a = ['a', 'a', 'a'];
let b = a.allValuesSame(); // true
a = ['a', 'b', 'a'];
b = a.allValuesSame();     // false
Robert Fricke
la source
5
très sympa, mais attention: IE ne prend pas en charge cette façon d'attribuer des prototypes. Je l'utilise quand même.
Tomáš Zato - Réintégrer Monica le
5
@ TomášZato: IE prend en charge l'augmentation du Array.prototypetrès bien (même IE6). Ce ne sont que des prototypes d'éléments DOM que certaines anciennes versions d'IE ne prennent pas en charge l'augmentation.
TJ Crowder
4
Je ne pense pas que ce soit une bonne idée d'être des prototypes intégrés de correction de singe. Si plusieurs bibliothèques le font, cela peut entraîner un comportement inattendu qui est très difficile à déboguer.
Mark Wilbur
1
@MarkWilbur +1 surtout si vous faites une boucle for..in sur les tableaux suivants, vous serez allValuesSamedans la boucle
Olivier Pons
1
Je suis allé de l'avant et j'ai modernisé cela, sans modifier l'intention.
M. Polywhirl le
30

Dans JavaScript 1.6, vous pouvez utiliser Array.every:

function AllTheSame(array) {
    var first = array[0];
    return array.every(function(element) {
        return element === first;
    });
}

Vous avez probablement besoin de quelques vérifications de cohérence, par exemple lorsque le tableau ne contient aucun élément. (De plus, cela ne fonctionnera pas lorsque tous les éléments sont NaNdepuis NaN !== NaN, mais cela ne devrait pas être un problème ... non?)

Mattias Buelens
la source
30

Vous pouvez transformer le tableau en un ensemble. Si la taille de l'ensemble est égale à 1, tous les éléments du tableau sont égaux.

function allEqual(arr) {
  return new Set(arr).size == 1;
}

allEqual(['a', 'a', 'a', 'a']); // true
allEqual(['a', 'a', 'b', 'a']); // false
Huy Tran
la source
Brillant. Notez juste que allEqual([NaN, NaN])donne truedans ce cas.
Константин Ван
12

Et pour la comparaison des performances, j'ai également fait un benchmark:

function allAreEqual(array){
    if(!array.length) return true;
    // I also made sure it works with [false, false] array
    return array.reduce(function(a, b){return (a === b)?a:(!b);}) === array[0];
}
function same(a) {
    if (!a.length) return true;
    return !a.filter(function (e) {
        return e !== a[0];
    }).length;
}

function allTheSame(array) {
    var first = array[0];
    return array.every(function(element) {
        return element === first;
    });
}

function useSome(array){
    return !array.some(function(value, index, array){
        return value !== array[0];
    });
}

Résultats:

allAreEqual x 47,565 ops/sec ±0.16% (100 runs sampled)
same x 42,529 ops/sec ±1.74% (92 runs sampled)
allTheSame x 66,437 ops/sec ±0.45% (102 runs sampled)
useSome x 70,102 ops/sec ±0.27% (100 runs sampled)

Donc, apparemment, utiliser array.some () intégré est la méthode la plus rapide de celles échantillonnées.

Martin
la source
3
Bonne idée de vérifier ce qui est le plus performant ici. La raison pour laquelle les Array#someperformances sont parfois surpassées est qu'une fois que la fonction de rappel retourne true, elle cesse d'itérer. Donc, si tous les éléments sont en fait égaux, les performances doivent être identiques à Array#every. Et les performances relatives lorsque tous les éléments ne sont pas égaux varient en fonction de l'indice du premier élément non correspondant.
danmactough
3
Joli. Vous pourriez avoir nommé chacun avec la fonction utilisée lol. Par exemple: réduire, filtrer, tous les, certains
Z. Khullah
où est la boucle for native, je parie que surpasse tout cela par un facteur de 5
PirateApp
9

Réponse la plus courte en utilisant un trait de soulignement / lodash

function elementsEqual(arr) {
    return !_.without(arr, arr[0]).length
}

spec:

elementsEqual(null) // throws error
elementsEqual([]) // true
elementsEqual({}) // true
elementsEqual([1]) // true
elementsEqual([1,2]) // false
elementsEqual(NaN) // true

Éditer:

Ou encore plus court, inspiré de la réponse de Tom:

function elementsEqual2(arr) {
    return _.uniq(arr).length <= 1;
}

spec:

elementsEqual2(null) // true (beware, it's different than above)
elementsEqual2([]) // true
elementsEqual2({}) // true
elementsEqual2([1]) // true
elementsEqual2([1,2]) // false
elementsEqual2(NaN) // true
Joe moyen
la source
6

Si vous utilisez déjà underscore.js , voici une autre option utilisant _.uniq:

function allEqual(arr) {
    return _.uniq(arr).length === 1;
}

_.uniqrenvoie une version sans doublon du tableau. Si toutes les valeurs sont identiques, la longueur sera 1.

Comme mentionné dans les commentaires, étant donné que vous pouvez vous attendre à ce qu'un tableau vide retourne true, vous devriez également vérifier ce cas:

function allEqual(arr) {
    return arr.length === 0 || _.uniq(arr).length === 1;
}
Tom Fenech
la source
Mais si le tableau est vide, votre réponse reviendra false. Alors que je pense que ça devrait l'être true. Changer en .length <= 1suffira cependant.
Joe moyen du
@Kasztan c'est un bon point. J'ai mis à jour ma réponse pour couvrir ce cas.
Tom Fenech
6

Oui, vous pouvez le vérifier également en utilisant le filtre comme ci-dessous, très simple, en vérifiant que toutes les valeurs sont les mêmes que la première:

//ES6
function sameValues(arr) {
  return arr.filter((v,i,a)=>v===a[0]).length === arr.length;
} 

peut également être fait en utilisant toutes les méthodes du tableau:

//ES6
function sameValues(arr) {
  return arr.every((v,i,a)=>v===a[0]);
} 

et vous pouvez vérifier vos tableaux comme ci-dessous:

sameValues(['a', 'a', 'a', 'a']); // true
sameValues(['a', 'a', 'b', 'a']); // false

Ou vous pouvez l'ajouter aux fonctionnalités natives de Array en JavaScript si vous le réutilisez beaucoup:

//ES6
Array.prototype.sameValues = Array.prototype.sameValues || function(){
 this.every((v,i,a)=>v===a[0]);
}

et vous pouvez vérifier vos tableaux comme ci-dessous:

['a', 'a', 'a', 'a'].sameValues(); // true
['a', 'a', 'b', 'a'].sameValues(); // false
Alireza
la source
5

Vous pouvez utiliser Array.everysi pris en charge:

var equals = array.every(function(value, index, array){
    return value === array[0];
});

L'approche alternative d'une boucle pourrait être quelque chose comme sort

var temp = array.slice(0).sort();
var equals = temp[0] === temp[temp.length - 1];

Ou, si les éléments sont comme la question, quelque chose de sale comme:

var equals = array.join('').split(array[0]).join('').length === 0;

Fonctionne aussi.

ZER0
la source
Vous avez le premier exemple à l'envers. Devrait être equals = !array.some( (v,i,a) => v!==a[0] ). Sinon, vous vérifiez simplement que toute valeur est égale à la première, ce qui sera bien sûr toujours vrai :)
Mark Kahn
Pas exactement, j'ai utilisé someau lieu de everycomme je l'ai mentionné dans le premier paragraphe. :) Merci pour la capture!
ZER0
5

Vous pouvez obtenir ce one-liner pour faire ce que vous voulez en utilisant les fonctions fléchées Array.prototype.every , Object.is et ES6:

const all = arr => arr.every(x => Object.is(arr[0], x));
Noor
la source
2
Veuillez décrire la solution que vous proposez.
il_raffa
3

Je pense que le moyen le plus simple de le faire est de créer une boucle pour comparer chaque valeur à la suivante. Tant qu'il y a une coupure dans la "chaîne", alors il retournera faux. Si le premier est égal au second, le second égal au troisième et ainsi de suite, alors nous pouvons conclure que tous les éléments du tableau sont égaux les uns aux autres.

étant donné un tableau de données [], alors vous pouvez utiliser:

for(x=0;x<data.length - 1;x++){
    if (data[x] != data[x+1]){
        isEqual = false;            
    }
}
alert("All elements are equal is " + isEqual);
Nicolas
la source
3
arr.length && arr.reduce(function(a, b){return (a === b)?a:false;}) === arr[0];
Martin
la source
3

Mettre à jour une nouvelle solution: vérifier l'index

 let a = ['a', 'a', 'b', 'a'];
 let a = ['a', 'a', 'a', 'a'];
 let check = (list) => list.every(item => list.indexOf(item) === 0);
 check(a); // false;
 check(b); // true;

Mise à jour avec ES6: l'utilisation list.everyest le moyen le plus rapide:

 let a = ['a', 'a', 'b', 'a'];
 let check = (list) => list.every(item => item === list[0]);

ancienne version:

      var listTrue = ['a', 'a', 'a', 'a'];
      var listFalse = ['a', 'a', 'a', 'ab'];

      function areWeTheSame(list) { 
         var sample = list[0];
         return (list.every((item) => item === sample));
      }
Kai
la source
2

Vous pouvez utiliser ceci:

function same(a) {
    if (!a.length) return true;
    return !a.filter(function (e) {
        return e !== a[0];
    }).length;
}

La fonction vérifie d'abord si le tableau est vide. Si c'est le cas, ses valeurs sont égales. Sinon, il filtre le tableau et prend tous les éléments qui sont différents du premier. S'il n'y a pas de telles valeurs => le tableau ne contient que des éléments égaux sinon ce n'est pas le cas.

Minko Gechev
la source
1

La _.isEqual(object, other)fonction de soulignement semble bien fonctionner pour les tableaux. L'ordre des éléments dans le tableau est important lorsqu'il vérifie l'égalité. Voir http://underscorejs.org/#isEqual .

Jon Onstott
la source
1
var listTrue = ['a', 'a', 'a', 'a'];
var listFalse = ['a', 'a', 'a', 'ab'];

function areWeTheSame(list) { 
    var sample = list[0];
    return !(list.some(function(item) {
        return !(item == sample);
    }));
}
user4861889
la source
Veuillez également expliquer ce que vous avez fait au lieu de simplement coller du code.
Wouter J
1

C'est simple. Créez une fonction et passez un paramètre. Dans cette fonction, copiez le premier index dans une nouvelle variable. Créez ensuite une boucle for et parcourez le tableau. À l'intérieur d'une boucle, créez une boucle while avec une condition vérifiant si la nouvelle variable créée est égale à tous les éléments de la boucle. si son égal retourne true après la fin de la boucle for else retourne false dans la boucle while.

function isUniform(arra){
    var k=arra[0];
    for (var i = 0; i < arra.length; i++) {
        while(k!==arra[i]){
            return false;
        }
    }
    return true;
}
Adithya Santhosh
la source
1

La réponse acceptée fonctionnait très bien mais je voulais ajouter un tout petit peu. Cela n'a pas fonctionné pour moi ===parce que je comparais des tableaux de tableaux d'objets, mais tout au long de mon application, j'ai utilisé le package fast-deep-equal que je recommande vivement. Avec cela, mon code ressemble à ceci:

let areAllEqual = arrs.every((val, i, arr) => equal(val, arr[0]) );

et mes données ressemblent à ceci:

[  
  [
    {
      "ID": 28,
      "AuthorID": 121,
      "VisitTypeID": 2
    },
    {
      "ID": 115,
      "AuthorID": 121,
      "VisitTypeID": 1
    },
    {
      "ID": 121,
      "AuthorID": 121,
      "VisitTypeID": 1
    }
  ],
  [
    {
      "ID": 121,
      "AuthorID": 121,
      "VisitTypeID": 1
    }
  ],
  [
    {
      "ID": 5,
      "AuthorID": 121,
      "VisitTypeID": 1
    },
    {
      "ID": 121,
      "AuthorID": 121,
      "VisitTypeID": 1
    }
  ]
]
Michael Aaron Wilson
la source
1
  1. Créez une chaîne en joignant le tableau.
  2. Créer une chaîne par répétition du premier caractère du tableau donné
  3. correspond aux deux chaînes

	function checkArray(array){
		return array.join("") == array[0].repeat(array.length);	
	}

	console.log('array: [a,a,a,a]: ' + checkArray(['a', 'a', 'a', 'a']));
	console.log('array: [a,a,b,a]: ' + checkArray(['a', 'a', 'b', 'a']));

Et vous avez terminé!

Rahul Vala
la source
1

Vous pouvez maintenant utiliser des ensembles pour le faire facilement.

let a= ['a', 'a', 'a', 'a']; // true
let b =['a', 'a', 'b', 'a'];// false

console.log(new Set(a).size === 1);
console.log(new Set(b).size === 1);

PC Krishnadas
la source
1

Vous pouvez utiliser une boucle for:

function isEqual(arr) {
  var first = arr[0];
  for (let i = 1; i < arr.length; i++) {
    if (first !== arr[i]) {
      return false;
    }
  }
  return true;
}
Armando Guarino
la source
0

Eh bien, ce n'est vraiment pas très compliqué. Je soupçonne fortement que vous n'avez même pas essayé. Ce que vous faites est de choisir la première valeur, de l'enregistrer dans la variable, puis, dans une forboucle, de comparer toutes les valeurs suivantes avec la première.
Je n'ai intentionnellement partagé aucun code. Trouvez comment forest utilisé et comment les variables sont comparées.

Tomáš Zato - Réintégrer Monica
la source
8
Je n'aime pas cette réponse. Cela ne vous permettrait pas de savoir si la deuxième valeur était la même que la troisième, etc. Évidemment, une boucle imbriquée le ferait, mais c'est conceptuellement différent pour un scripteur novice.
jtromans
3
@jtromans: à cause de la propriété transitive d'égalité, si A == B et A == C alors nous savons B == C; vous n'avez pas à le vérifier "manuellement" avec une boucle imbriquée, etc.
ov
@ov En effet, dans ma hâte, j'ai mal lu la question, ce qui, je pensais à l'époque, nécessitait plus que simplement vérifier que toutes les valeurs sont égales (! duh).
jtromans
9
C'est pas compliqué. Et les autres réponses sur la page non plus. Mais pour moi, cette réponse est de loin la moins utile.
Charlie le
1
Il visait à l'origine à faire un point fort vers le PO en insistant sur le fait qu'il essaie de réfléchir avant de poser des questions.
Tomáš Zato - Réintégrer Monica le
0

Solution simple d'une ligne, comparez-la simplement à un tableau rempli avec la première entrée.

if(arr.join('') === Array(arr.length).fill(arr[0]).join(''))
Pyviet
la source
Cela ne semble pas être une solution qui peut être utilisée n'importe où
Lu4
C'est assez proche de ok. Mieux vaut quelque chose comme: function arrayOfSame (arr) {return (arr.join ('') == (new Array (arr.length + 1) .join (arr [0]))); }
Arkain
0

Une autre façon intéressante d'utiliser la syntaxe de la fonction de flèche ES6:

x = ['a', 'a', 'a', 'a']
!x.filter(e=>e!==x[0])[0]  // true

x = ['a', 'a', 'b', 'a']
!x.filter(e=>e!==x[0])[0] // false

x = []
!x.filter(e=>e!==x[0])[0]  // true

Et quand vous ne voulez pas réutiliser la variable pour array (x):

!['a', 'a', 'a', 'a'].filter((e,i,a)=>e!==a[0])[0]    // true

L'affiche précédente de l'OMI qui a utilisé array.every (...) a la solution la plus propre.

Tomasz Szawara
la source
0
function isUniform(array) {   
  for (var i=1; i< array.length; i++) {
    if (array[i] !== array[0]) { return false; }
  }

  for (var i=1; i< array.length; i++) {
    if (array[i] === array[0]) { return true; }
  }
}
  • Pour la première boucle; chaque fois qu'il détecte des irrégularités, renvoie "faux"
  • La première boucle s'exécute, et si elle retourne false, nous avons "false"
  • Quand ce n'est pas de retour faux, cela signifie qu'il y aura vrai, donc nous faisons la deuxième boucle. Et bien sûr, nous aurons "true" de la deuxième boucle (car la première boucle a trouvé que ce n'est PAS faux)
Jaden Tran
la source
0

cela pourrait fonctionner, vous pouvez également utiliser le code de commentaire qui fonctionne également bien avec le scénario donné.

function isUniform(){
	var arrayToMatch = [1,1,1,1,1];
	var temp = arrayToMatch[0];
	console.log(temp);
  /* return arrayToMatch.every(function(check){
    return check == temp;
   });*/
var bool;
   arrayToMatch.forEach(function(check){
    bool=(check == temp);
   })
  console.log(bool);
}
isUniform();

Aman Pathak
la source
0

Une autre façon avec une taille délimitée et une liste organisée:

tableau1 = [1,2,3]; tableau2 = [1,2,3];

function isEqual(){

    return array1.toString()==array2.toString();
}
Fábio Balbino
la source
0

Vous pouvez convertir un tableau en un ensemble et vérifier sa taille

Dans le cas d'entrées de tableaux primitifs, c'est number-à- dire string:

const isArrayWithEqualEntries = array => new Set(array).size === 1

Dans le cas d'un tableau d'objets avec un champ à tester pour l'équivalence, dites id:

const mapper = ({id}) => id
const isArrayWithEqualEntries = array => new Set(array.map(mapper)).size === 1
Simon
la source
-4

En PHP, il existe une solution très simple, une méthode en une ligne:

(count (array_count_values ​​($ array)) == 1)

Par exemple :

$arr1 = ['a', 'a', 'a', 'a'];
$arr2 = ['a', 'a', 'b', 'a'];


print (count(array_count_values($arr1)) == 1 ? "identical" : "not identical"); // identical
print (count(array_count_values($arr2)) == 1 ? "identical" : "not identical"); // not identical

C'est tout.

Jerry
la source