Sprawdź, czy wszystkie wartości tablicy są równe

190

Muszę znaleźć tablice, w których wszystkie wartości są równe. Jaki jest najszybszy sposób to zrobić? Czy powinienem przez to przejść i po prostu porównać wartości?

['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false
Marvin3
źródło
1
@TJCrowder Założę się, że już myślisz o najlepszym rozwiązaniu;)
VisioN
2
@TJCrowder: Nie wspominając już o gotowości pytających do faktycznego przyjmowania odpowiedzi. Użytkownicy z 1 powtórzeniem często wydają się pytać i uruchamiać typy, które wychodzą, gdy tylko mają ostatnio odpowiedź na możliwość skopiowania i wklejenia.
Cerbrus
1
Coś wokół tego podejścia powinno działać? a.join(',').split(a[0]).length === a.length + 1
Jashwant
1
@ TomášZato: „OP” oznacza „oryginalny plakat” (osoba zadająca pytanie).
TJ Crowder

Odpowiedzi:

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

Lub jednowarstwowy:

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

Array.prototype.every (z MDN):every() Metoda sprawdza, czy wszystkie elementy w tablicy przechodzą test zaimplementowany przez podaną funkcję.

golopot
źródło
10
Zwięzłość jest duszą wit
svaroga
1
Utworzyłem skrzynkę jsperf . Ta metoda przewyższa większość kandydatów.
Junliang Huang
1
const everythings_equal = array => array.every(thing => thing === array[0]);
Константин Ван
8
Użyj somezamiast every: arr.some( v => v !== arr[0] ). Wróci wcześniej, gdy pierwszy element będzie nierówny arr[0].
stycznia
2
@Jan everyrównież szybko wraca.
golopot
111

Edycja: Bądź czerwonym ninja:

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

Wyniki:

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" 

Ostrzeżenie:

var array = [] => result: TypeError thrown

Wynika to z faktu, że nie przekazujemy wartości początkowej . Więc możesz array.lengthnajpierw sprawdzić .

Jaskółka oknówka
źródło
5
może być trochę spóźniony na imprezę ... myślę, że to nie działa, jeśli twoja tablica jest wykonana z falses! na przykład spróbuj [false, false, false] .reduce (function (a, b) {return (a === b)? a: false;});
George Flourentzos
3
@Martin: ["false", ""]zwraca true: /
dalgard
6
Można to zrobić za pomocą wycięcia NaN. Ponieważ oba NaN === NaNi NaN !== NaNsą fałszywe, to gwarantuje, że gdy prevjest ustawiony na wartość NaN wtedy nie można go wyjąć. Również dodanie podwójnej negacji przekształca wyniki na truei false, ponieważ NaNjest to fałsz. Forma końcowa:!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
Filipe Silva,
3
Downvoted . Co jeśli elementy są równe, ale fałszywe ?
Константин Ван
3
Odrzuciłem głos, ponieważ nie działa to z wartościami logicznymi.
Tyguy7
62

To działa. Metodę tworzy się na macierzy przy użyciu prototypu.

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

Nazwij to w ten sposób:

let a = ['a', 'a', 'a'];
let b = a.allValuesSame(); // true
a = ['a', 'b', 'a'];
b = a.allValuesSame();     // false
Robert Fricke
źródło
5
bardzo fajnie, ale uwaga: IE nie obsługuje tego sposobu przypisywania prototypów. I tak go używam.
Tomáš Zato - Przywróć Monikę
5
@ TomášZato: IE obsługuje zwiększanie Array.prototypegrzywny (nawet IE6). To tylko prototypy elementów DOM, że niektóre starsze wersje IE nie obsługują rozszerzania.
TJ Crowder
4
Nie sądzę, że dobrym pomysłem jest łatanie małp wbudowanych prototypów. Jeśli zrobi to wiele bibliotek, może to prowadzić do nieoczekiwanego zachowania, które jest bardzo trudne do debugowania.
Mark Wilbur,
1
@ MarkWilbur +1, zwłaszcza jeśli wykonasz pętlę for..in na kolejnych tablicach, dostaniesz się allValuesSamedo pętli
Olivier Pons
1
Poszedłem do przodu i zmodernizowałem to, nie zmieniając intencji.
Pan Polywhirl
30

W JavaScript 1.6 możesz użyć Array.every:

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

Prawdopodobnie potrzebujesz pewnych sprawdzeń poprawności, np. Gdy tablica nie ma elementów. (Również to nie zadziała, gdy wszystkie elementy są NaNodtąd NaN !== NaN, ale to nie powinno być problemem ... prawda?)

Mattias Buelens
źródło
30

Możesz zmienić tablicę w zestaw. Jeśli rozmiar zestawu jest równy 1, wówczas wszystkie elementy tablicy są równe.

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

allEqual(['a', 'a', 'a', 'a']); // true
allEqual(['a', 'a', 'b', 'a']); // false
Huy Tran
źródło
Znakomity. Pamiętaj tylko, że allEqual([NaN, NaN])daje trueto w tym przypadku.
Константин Ван
12

I dla porównania wydajności zrobiłem też test porównawczy:

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

Wyniki:

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)

Najwyraźniej użycie wbudowanej array.some () jest najszybszą metodą z tych, z których próbkowano.

Jaskółka oknówka
źródło
3
Dobry pomysł, aby sprawdzić, co jest bardziej wydajne tutaj. Powodem, dla którego Array#someczasami osiąga lepsze wyniki, jest to, że gdy funkcja zwrotna zwraca wartość true, przestaje iterować. Tak więc, jeśli wszystkie elementy są w rzeczywistości równe, wydajność powinna być identyczna Array#every. Względna wydajność, gdy wszystkie elementy nie są równe, będzie się różnić w zależności od indeksu pierwszego niepasującego elementu.
danmactough
3
Niezłe. Mógłbyś nazwać każdego przy użyciu funkcji lol. Np .: zmniejsz, filtruj, co jakiś
Z. Khullah,
gdzie jest natywna dla pętli, założę się, że przewyższa je wszystkie o współczynnik 5
PirateApp
9

Najkrótsza odpowiedź przy użyciu podkreślenia / 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

edytować:

Lub nawet krócej, zainspirowany odpowiedzią Toma:

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
przeciętny Joe
źródło
6

Jeśli już używasz underscore.js , oto inna opcja, używając _.uniq:

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

_.uniqzwraca wersję tablicy bez duplikatów. Jeśli wszystkie wartości są takie same, długość będzie wynosić 1.

Jak wspomniano w komentarzach, biorąc pod uwagę, że możesz spodziewać się zwrócenia pustej tablicy true, powinieneś również sprawdzić ten przypadek:

function allEqual(arr) {
    return arr.length === 0 || _.uniq(arr).length === 1;
}
Tom Fenech
źródło
Ale jeśli tablica jest pusta, twoja odpowiedź wróci false. Chociaż myślę, że tak powinno być true. Zmiana na .length <= 1musi być na tyle chociaż.
średni Joe
@Kasztan to słuszna kwestia. Zaktualizowałem swoją odpowiedź, aby uwzględnić tę sprawę.
Tom Fenech
6

Tak, możesz to sprawdzić również za pomocą filtra, jak poniżej, bardzo proste, sprawdzanie, czy wszystkie wartości są takie same jak pierwsza:

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

Można to również zrobić za pomocą każdej metody w tablicy:

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

i możesz sprawdzić swoje tablice, jak poniżej:

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

Możesz też dodać go do natywnych funkcji Array w JavaScript, jeśli często go użyjesz:

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

i możesz sprawdzić swoje tablice, jak poniżej:

['a', 'a', 'a', 'a'].sameValues(); // true
['a', 'a', 'b', 'a'].sameValues(); // false
Alireza
źródło
5

Możesz użyć, Array.everyjeśli obsługiwane:

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

Alternatywne podejście do pętli może być podobne sort

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

Lub, jeśli przedmioty są jak pytanie, coś brudnego jak:

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

Działa również.

ZER0
źródło
Pierwszy przykład masz do tyłu. Powinno być equals = !array.some( (v,i,a) => v!==a[0] ). W przeciwnym razie sprawdzasz tylko, czy jakakolwiek wartość jest równa pierwszej, co oczywiście zawsze będzie prawdziwe :)
Mark Kahn
Nie do końca, użyłem somezamiast, everyjak wspomniałem w pierwszym akapicie. :) Dzięki za połów!
ZER0
5

Możesz uzyskać ten jeden wiersz do robienia tego, co chcesz, korzystając z funkcji strzałek Array.prototype.every , Object.is i ES6:

const all = arr => arr.every(x => Object.is(arr[0], x));
Noor
źródło
2
Opisz proponowane rozwiązanie.
il_raffa
3

Myślę, że najprostszym sposobem na to jest utworzenie pętli, aby porównać każdą wartość z następną. Dopóki nastąpi przerwa w „łańcuchu”, wówczas zwróci wartość false. Jeśli pierwszy jest równy drugiemu, drugi równy jest trzeciemu itd., Możemy stwierdzić, że wszystkie elementy tablicy są sobie równe.

biorąc pod uwagę dane tablicy [], możesz użyć:

for(x=0;x<data.length - 1;x++){
    if (data[x] != data[x+1]){
        isEqual = false;            
    }
}
alert("All elements are equal is " + isEqual);
Mikołaj
źródło
3
arr.length && arr.reduce(function(a, b){return (a === b)?a:false;}) === arr[0];
Jaskółka oknówka
źródło
3

Zaktualizuj nowe rozwiązanie: sprawdź indeks

 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;

Zaktualizowany z ES6: użycie list.everyjest najszybszym sposobem:

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

stara wersja:

      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
źródło
2

Możesz użyć tego:

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

Funkcja najpierw sprawdza, czy tablica jest pusta. Jeśli tak, to jego wartości są równe. W przeciwnym razie filtruje tablicę i pobiera wszystkie elementy, które różnią się od pierwszego. Jeśli nie ma takich wartości => tablica zawiera tylko równe elementy, inaczej nie.

Minko Gechev
źródło
1

_.isEqual(object, other)Funkcja podkreślenia wydaje się działać dobrze dla tablic. Kolejność elementów w tablicy ma znaczenie przy sprawdzaniu równości. Zobacz http://underscorejs.org/#isEqual .

Jon Onstott
źródło
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);
    }));
}
użytkownik4861889
źródło
Wyjaśnij także, co zrobiłeś, zamiast wkleić kod.
Wouter J
1

To proste. Utwórz funkcję i przekaż parametr. W tej funkcji skopiuj pierwszy indeks do nowej zmiennej. Następnie utwórz pętlę for i wykonaj pętlę przez tablicę. Wewnątrz pętli utwórz pętlę while z warunkiem sprawdzającym, czy nowa utworzona zmienna jest równa wszystkim elementom w pętli. jeśli jego równość zwraca true po zakończeniu pętli for, w przeciwnym razie zwraca false w pętli 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
źródło
1

Akceptowane odpowiedź działał świetnie, ale chciałem dodać odrobinę. Nie działało dla mnie, ===ponieważ porównywałem tablice obiektów, jednak w mojej aplikacji korzystałem z pakietu szybkiego i głębokiego równości , który bardzo polecam. Dzięki temu mój kod wygląda następująco:

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

a moje dane wyglądają tak:

[  
  [
    {
      "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
źródło
1
  1. Utwórz ciąg, dołączając do tablicy.
  2. Utwórz ciąg, powtarzając pierwszy znak danej tablicy
  3. dopasuj oba ciągi

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

I jesteś GOTOWY!

Rahul Vala
źródło
1

Teraz możesz łatwo korzystać z zestawów.

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
źródło
1

Możesz użyć pętli 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
źródło
0

To naprawdę nie jest bardzo skomplikowane. Mam silne podejrzenia, że ​​nawet nie próbowałeś. Robisz to, że wybierasz pierwszą wartość, zapisujesz ją w zmiennej, a następnie, w forpętli, porównujesz wszystkie kolejne wartości z pierwszą.
Celowo nie udostępniłem żadnego kodu. Znajdź sposób forużycia i porównania zmiennych.

Tomáš Zato - Przywróć Monikę
źródło
8
Nie podoba mi się ta odpowiedź. Nie dałoby ci znać, czy druga wartość jest taka sama jak trzecia itd. Oczywiście zagnieżdżona pętla by to zrobiła, ale to koncepcyjnie różni się od początkującego skryptu.
jtromans
3
@jtromans: ze względu na przechodnią właściwość równości, jeśli A == B i A == C, to znamy B == C; nie musisz weryfikować go „ręcznie” za pomocą zagnieżdżonej pętli itp. Powtarzające się porównanie z pojedynczą wartością (pierwsza wartość w tablicy, a nie dowolna :) jest dokładnie tym, co sugeruje ta odpowiedź, podobnie jak zaakceptowana odpowiedź.
dniu
@ov Rzeczywiście, w pośpiechu źle odczytałem pytanie, które w tym czasie myślałem, że wymagało czegoś więcej niż tylko sprawdzenia, czy wszystkie wartości są równe (! duh).
jtromans
9
To nie jest skomplikowane. I nie ma też innych odpowiedzi na stronie. Ale dla mnie ta odpowiedź jest zdecydowanie najmniej pomocna.
Charlie,
1
Pierwotnie miał on stanowić mocny punkt w stosunku do OP, nalegając, aby spróbował pomyśleć przed zadaniem pytań.
Tomáš Zato - Przywróć Monikę
0

Proste rozwiązanie jednowierszowe, wystarczy porównać je z tablicą wypełnioną pierwszym wpisem.

if(arr.join('') === Array(arr.length).fill(arr[0]).join(''))
pyviet
źródło
To nie wydaje się rozwiązaniem, którego można by użyć wszędzie
Lu4,
Jest całkiem blisko ok. Lepiej byłoby coś takiego: function arrayOfSame (arr) {return (arr.join ('') == (new Array (arr.length + 1) .join (arr [0]))); }
Arkain,
0

Kolejny interesujący sposób korzystania ze składni funkcji strzałek 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

A jeśli nie chcesz ponownie użyć zmiennej dla tablicy (x):

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

Poprzedni plakat IMO, który używał tablicy. Każde (...) ma najczystsze rozwiązanie.

Tomasz Szawara
źródło
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; }
  }
}
  • Dla pierwszej pętli; ilekroć wykryje nierówność, zwraca „fałsz”
  • Pierwsza pętla działa, a jeśli zwróci false, mamy „false”
  • Gdy nie jest zwracane false, oznacza to, że będzie prawda, więc wykonujemy drugą pętlę. I oczywiście będziemy mieli „prawda” z drugiej pętli (ponieważ pierwsza pętla okazała się NIE jest fałszywa)
Jaden Tran
źródło
0

to może zadziałać, możesz również użyć kodu komentowania, który również dobrze działa w danym scenariuszu.

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
źródło
0

Inny sposób z ograniczonym rozmiarem i uporządkowaną listą:

tablica 1 = [1,2,3]; tablica 2 = [1,2,3];

function isEqual(){

    return array1.toString()==array2.toString();
}
Fábio Balbino
źródło
0

Możesz przekonwertować tablicę na zestaw i sprawdzić jej rozmiar

W przypadku prymitywnych wpisów tablicy, to znaczy number, string:

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

W przypadku tablicy obiektów z pewnym polem do przetestowania pod kątem równoważności, powiedz id:

const mapper = ({id}) => id
const isArrayWithEqualEntries = array => new Set(array.map(mapper)).size === 1
Szymon
źródło
-4

W PHP istnieje rozwiązanie bardzo proste, metoda jednoliniowa:

(liczba (wartości_licznika_wartości ($ tablica)) == 1)

Na przykład :

$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

To wszystko.

Nocnik
źródło