Überprüfen Sie, ob alle Werte des Arrays gleich sind

188

Ich muss Arrays finden, in denen alle Werte gleich sind. Was ist der schnellste Weg, dies zu tun? Soll ich es durchlaufen und nur Werte vergleichen?

['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false
Marvin3
quelle
1
@TJCrowder Ich wette, Sie denken bereits über die beste Lösung nach;)
VisioN
2
@TJCrowder: Ganz zu schweigen von der Bereitschaft der Fragesteller, Antworten tatsächlich anzunehmen. Benutzer mit 1 Wiederholung scheinen häufig Ask & Run-Typen zu sein, die in letzter Zeit abreisen, sobald sie eine Antwort zum Kopieren und Einfügen haben.
Cerbrus
1
Etwas um diesen Ansatz sollte funktionieren? a.join(',').split(a[0]).length === a.length + 1
Jashwant
1
@ TomášZato: "OP" bedeutet "Originalplakat" (die Person, die die Frage stellt).
TJ Crowder

Antworten:

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

Oder einzeilig:

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

Array.prototype.every (von MDN): Die every()Methode testet, ob alle Elemente im Array den von der bereitgestellten Funktion implementierten Test bestehen.

Golopot
quelle
10
Kürze ist die Seele des Witzes
svarog
1
Ich habe einen jsperf-Fall erstellt . Diese Methode übertrifft die meisten Kandidaten.
Junliang Huang
1
const everythings_equal = array => array.every(thing => thing === array[0]);
25онстантин Ван
8
Verwenden Sie someanstelle von every: arr.some( v => v !== arr[0] ). Dies wird früh zurückkehren, wenn das erste Element als ungleich befunden wird arr[0].
Jan
2
@Jan everykehrt auch früh zurück.
Golopot
111

Edit: Sei ein roter Ninja:

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

Ergebnisse:

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" 

Warnung:

var array = [] => result: TypeError thrown

Dies liegt daran, dass wir keinen initialValue übergeben . Vielleicht möchten Sie array.lengthzuerst überprüfen .

Martin
quelle
5
Vielleicht ist es etwas spät für die Party ... Ich denke, das funktioniert nicht, wenn dein Array aus falses besteht! Beispiel: try [false, false, false] .reduce (Funktion (a, b) {return (a === b)? a: false;});
George Flourentzos
3
@ Martin: ["false", ""]Rückkehr true: /
Dalgard
6
Dies kann mit verwendet werden NaN. Da beide NaN === NaNund NaN !== NaNfalsch sind, wird garantiert, dass prevkein Wert , sobald der auf NaN gesetzt ist, herausgenommen werden kann. Durch Hinzufügen einer doppelten Negation werden die Ergebnisse in trueund konvertiert false, da dies NaNfalsch ist. Endgültige Form:!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
Filipe Silva
3
DOWNVOTED . Was ist, wenn die Elemente gleich, aber falsch sind ?
25онстант .н Ван
3
Ich habe abgestimmt, weil dies mit booleschen Werten nicht funktioniert.
Tyguy7
62

Das funktioniert. Sie erstellen eine Methode für Array mithilfe eines Prototyps.

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

Nennen Sie dies so:

let a = ['a', 'a', 'a'];
let b = a.allValuesSame(); // true
a = ['a', 'b', 'a'];
b = a.allValuesSame();     // false
Robert Fricke
quelle
5
sehr schön, aber Vorsicht: IE unterstützt diese Art der Zuweisung von Prototypen nicht. Ich benutze es trotzdem.
Tomáš Zato - Wiedereinsetzung Monica
5
@ TomášZato: IE unterstützt die Erweiterung des Array.prototypeFeinen (sogar IE6). Es sind nur DOM-Element-Prototypen, die von einigen älteren Versionen des IE nicht erweitert werden.
TJ Crowder
4
Ich denke nicht, dass es eine gute Idee ist, eingebaute Prototypen mit Affen zu patchen. Wenn mehrere Bibliotheken dies tun, kann dies zu unerwartetem Verhalten führen, das nur sehr schwer zu debuggen ist.
Mark Wilbur
1
@ MarkWilbur +1 vor allem, wenn Sie eine for..in-Schleife auf nächsten Arrays machen, werden Sie allValuesSamein der Schleife bekommen
Olivier Pons
1
Ich ging voran und modernisierte dies, ohne die Absicht zu ändern.
Mr. Polywhirl
30

In JavaScript 1.6 können Sie Folgendes verwenden Array.every:

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

Sie benötigen wahrscheinlich einige Sicherheitsüberprüfungen, z. B. wenn das Array keine Elemente enthält. (Auch dies wird nicht funktionieren, wenn alle Elemente NaNseitdem vorhanden sind NaN !== NaN, aber das sollte kein Problem sein ... richtig?)

Mattias Buelens
quelle
30

Sie können das Array in ein Set verwandeln. Wenn die Größe des Sets gleich 1 ist, sind alle Elemente des Arrays gleich.

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

allEqual(['a', 'a', 'a', 'a']); // true
allEqual(['a', 'a', 'b', 'a']); // false
Huy Tran
quelle
Brillant. Nur beachten Sie, dass allEqual([NaN, NaN])gibt truein diesem Fall.
25онстантин Ван
12

Und zum Leistungsvergleich habe ich auch einen Benchmark gemacht:

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

Ergebnisse:

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)

Die Verwendung von integriertem Array.some () ist anscheinend die schnellste der untersuchten Methoden.

Martin
quelle
3
Gute Idee zu überprüfen, was hier performanter ist. Der Grund, warum Array#somemanchmal eine Outperformance erzielt wird, ist, dass die Rückruffunktion nicht mehr iteriert, sobald sie true zurückgibt. Wenn also tatsächlich alle Elemente gleich sind, sollte die Leistung identisch sein mit Array#every. Und die relative Leistung, wenn nicht alle Elemente gleich sind, hängt vom Index des ersten nicht übereinstimmenden Elements ab.
Danmactough
3
Schön. Sie hätten jeden mit der verwendeten Funktion lol benennen können. ZB: reduzieren, filtern, alle, einige
Z. Khullah
Ich wette, dass all dies um den Faktor 5
übertrifft
9

Kürzeste Antwort mit Unterstrich / 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

bearbeiten:

Oder noch kürzer, inspiriert von Toms Antwort:

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
Durchschnittstyp
quelle
6

Wenn Sie bereits underscore.js verwenden , können Sie Folgendes verwenden _.uniq:

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

_.uniqGibt eine duplikationsfreie Version des Arrays zurück. Wenn alle Werte gleich sind, beträgt die Länge 1.

Wie in den Kommentaren erwähnt, sollten Sie angesichts der Tatsache, dass Sie möglicherweise erwarten, dass ein leeres Array zurückkehrt true, auch nach diesem Fall suchen:

function allEqual(arr) {
    return arr.length === 0 || _.uniq(arr).length === 1;
}
Tom Fenech
quelle
Wenn das Array jedoch leer ist, wird Ihre Antwort zurückgegeben false. Während ich denke, dass es sein sollte true. Ein Wechsel zu .length <= 1soll jedoch ausreichen.
Durchschnitt Joe
@ Kasztan das ist ein fairer Punkt. Ich habe meine Antwort aktualisiert, um diesen Fall abzudecken.
Tom Fenech
6

Ja, Sie können es auch mit dem folgenden Filter überprüfen, ganz einfach, indem Sie überprüfen, ob alle Werte mit denen des ersten identisch sind:

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

kann auch mit jeder Methode auf dem Array durchgeführt werden:

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

und Sie können Ihre Arrays wie folgt überprüfen:

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

Oder Sie können es nativen Array-Funktionen in JavaScript hinzufügen, wenn Sie es häufig wiederverwenden:

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

und Sie können Ihre Arrays wie folgt überprüfen:

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

Sie können verwenden, Array.everywenn unterstützt:

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

Der alternative Ansatz einer Schleife könnte so etwas wie sein sort

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

Oder, wenn die Gegenstände wie die Frage sind, etwas Schmutziges wie:

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

Funktioniert auch.

ZER0
quelle
Sie haben das erste Beispiel rückwärts. Sollte sein equals = !array.some( (v,i,a) => v!==a[0] ). Ansonsten prüfst du nur, ob irgendein Wert dem ersten entspricht, was natürlich immer wahr sein wird :)
Mark Kahn
Nicht genau, ich habe somestatt everywie im ersten Absatz erwähnt verwendet. :) Danke für den Fang!
ZER0
3

Ich denke, der einfachste Weg, dies zu tun, besteht darin, eine Schleife zu erstellen, um jeden Wert mit dem nächsten zu vergleichen. Solange es einen Bruch in der "Kette" gibt, würde es false zurückgeben. Wenn das erste gleich dem zweiten, das zweite gleich dem dritten usw. ist, können wir schließen, dass alle Elemente des Arrays gleich sind.

Wenn Sie Array-Daten [] haben, können Sie Folgendes verwenden:

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

Neue Lösung aktualisieren: Index prüfen

 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;

Mit ES6 aktualisiert: Verwendung list.everyist der schnellste Weg:

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

alte 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
quelle
2

Sie können dies verwenden:

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

Die Funktion prüft zunächst, ob das Array leer ist. Wenn dies der Fall ist, sind die Werte gleich. Andernfalls wird das Array gefiltert und alle Elemente verwendet, die sich vom ersten unterscheiden. Wenn es keine solchen Werte gibt => enthält das Array nur gleiche Elemente, sonst nicht.

Minko Gechev
quelle
1

Die _.isEqual(object, other)Funktion von Underscore scheint für Arrays gut zu funktionieren. Die Reihenfolge der Elemente im Array spielt eine Rolle, wenn die Gleichheit überprüft wird. Siehe http://underscorejs.org/#isEqual .

Jon Onstott
quelle
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
quelle
Bitte erklären Sie auch, was Sie getan haben, anstatt nur Code einzufügen.
Wouter J
1

Es ist einfach. Erstellen Sie eine Funktion und übergeben Sie einen Parameter. Kopieren Sie in dieser Funktion den ersten Index in eine neue Variable. Erstellen Sie dann eine for-Schleife und durchlaufen Sie das Array. Erstellen Sie innerhalb einer Schleife eine while-Schleife mit einer Bedingung, die überprüft, ob die neu erstellte Variable allen Elementen in der Schleife entspricht. Wenn die gleiche Rückgabe nach Abschluss der for-Schleife true ist, wird innerhalb der while-Schleife false zurückgegeben.

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
quelle
1

Die akzeptierte Antwort funktionierte großartig, aber ich wollte ein kleines bisschen hinzufügen. Die Verwendung hat bei mir nicht funktioniert, ===da ich Arrays von Arrays von Objekten verglichen habe. In meiner gesamten App habe ich jedoch das Fast-Deep-Equal- Paket verwendet, das ich sehr empfehlen kann. Damit sieht mein Code folgendermaßen aus:

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

und meine Daten sehen so aus:

[  
  [
    {
      "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
quelle
1
  1. Erstellen Sie eine Zeichenfolge, indem Sie das Array verbinden.
  2. Erstellen Sie eine Zeichenfolge durch Wiederholung des ersten Zeichens des angegebenen Arrays
  3. passen beide Saiten an

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

Und du bist fertig!

Rahul Vala
quelle
1

Jetzt können Sie Sets verwenden, um dies einfach zu tun.

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

Krishnadas PC
quelle
1

Sie könnten eine for-Schleife verwenden:

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
quelle
0

Nun, das ist wirklich nicht sehr kompliziert. Ich habe den starken Verdacht, dass Sie es nicht einmal versucht haben. Sie wählen den ersten Wert aus, speichern ihn in der Variablen und vergleichen dann innerhalb einer forSchleife alle nachfolgenden Werte mit dem ersten.
Ich habe absichtlich keinen Code geteilt. Finden Sie heraus for, wie Variablen verwendet und verglichen werden.

Tomáš Zato - Monica wieder einsetzen
quelle
8
Diese Antwort gefällt mir nicht. Es würde Sie nicht wissen lassen, ob der zweite Wert der gleiche wie der dritte ist usw. Offensichtlich würde eine verschachtelte Schleife dies tun, aber das unterscheidet sich konzeptionell von einem unerfahrenen Scripter.
Jtromans
3
@jtromans: Aufgrund der transitiven Eigenschaft der Gleichheit kennen wir B == C, wenn A == B und A == C; Sie müssen es nicht "manuell" mit einer verschachtelten Schleife usw. überprüfen. Der wiederholte Vergleich mit einem einzelnen Wert (erster Wert im Array, kein beliebiger Wert :) ist genau das, was diese Antwort vorschlägt, ebenso wie die akzeptierte Antwort.
Ov
@ov In meiner Eile habe ich die Frage falsch verstanden, von der ich damals dachte, dass sie mehr erfordert, als nur zu überprüfen, ob alle Werte gleich sind (! duh).
Jtromans
9
Es ist nicht kompliziert. Und die anderen Antworten auf der Seite sind auch nicht. Aber für mich ist diese Antwort bei weitem am wenigsten hilfreich.
Charlie
1
Es sollte ursprünglich einen starken Punkt gegenüber dem OP machen und darauf bestehen, dass er versucht zu denken, bevor er Fragen stellt.
Tomáš Zato - Wiedereinsetzung Monica
0

Einfache einzeilige Lösung, vergleichen Sie sie einfach mit einem Array, das mit dem ersten Eintrag gefüllt ist.

if(arr.join('') === Array(arr.length).fill(arr[0]).join(''))
pyviet
quelle
Das scheint keine Lösung zu sein, die überall eingesetzt werden kann
Lu4
Es ist ziemlich nah an ok. Besser wäre so etwas wie: function arrayOfSame (arr) {return (arr.join ('') == (neues Array (arr.length + 1) .join (arr [0]))); }
Arkain
0

Ein weiterer interessanter Weg, wenn Sie die ES6-Pfeilfunktionssyntax verwenden:

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

Und wenn Sie die Variable für Array (x) nicht wiederverwenden möchten:

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

IMO vorheriges Poster, das array.every (...) verwendet hat, hat die sauberste Lösung.

Tomasz Szawara
quelle
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; }
  }
}
  • Für die erste Schleife; Wenn es Unebenheiten erkennt, wird "false" zurückgegeben.
  • Die erste Schleife wird ausgeführt, und wenn sie false zurückgibt, haben wir "false".
  • Wenn es nicht false zurückgibt, bedeutet dies, dass es true gibt, also machen wir die zweite Schleife. Und natürlich haben wir "wahr" aus der zweiten Schleife (weil die erste Schleife festgestellt hat, dass es NICHT falsch ist)
Jaden Tran
quelle
0

Dies könnte funktionieren. Sie können auch den Kommentar-Code verwenden, der auch mit dem angegebenen Szenario gut funktioniert.

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
quelle
0

Ein anderer Weg mit begrenzter Größe und organisierter Liste:

Array1 = [1,2,3]; Array2 = [1,2,3];

function isEqual(){

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

Sie können ein Array in ein Set konvertieren und dessen Größe überprüfen

Im Fall eines primitiven Feldeinträge, das heißt number, string:

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

Im Fall einer Anordnung von Objekten mit einem Feld, das auf Äquivalenz getestet werden soll, sagen Sie id:

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

In PHP gibt es eine sehr einfache einzeilige Lösung:

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

Zum Beispiel :

$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

Das ist alles.

Jerry
quelle