Dizinin tüm değerlerinin eşit olup olmadığını kontrol edin


190

Tüm değerlerin eşit olduğu diziler bulmam gerekiyor. Bunu yapmanın en hızlı yolu nedir? Ben döngü ve sadece değerleri karşılaştırmak gerekir?

['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false

1
@TJCrowder Eminim zaten en iyi çözümü düşünüyorsunuz;)
VisioN

2
@TJCrowder: Soru soranların cevapları gerçekten kabul etme istekliliğinden bahsetmiyorum bile. 1 temsilcisi olan kullanıcılar genellikle, kopyala yapıştır özelliğine sahip bir cevap alır almaz bırakılan sor ve çalıştır türleri gibi görünüyor.
Cerbrus

1
Bu yaklaşımın etrafında bir şey olmalı mı? a.join(',').split(a[0]).length === a.length + 1
Jashwant

1
@ TomášZato: "OP", "orijinal poster" (soruyu soran kişi) anlamına gelir.
TJ Crowder

Yanıtlar:


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

Veya tek astarlı:

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

Array.prototype.every (MDN'den): every()Yöntem, dizideki tüm öğelerin sağlanan işlev tarafından uygulanan testi geçip geçmediğini test eder.


12

1
Bir jsperf davası oluşturdum . Bu yöntem çoğu adaydan daha iyi performans gösterir.
Junliang Huang

1
const everythings_equal = array => array.every(thing => thing === array[0]);
Константин Ван

8
Kullanım someyerine every: arr.some( v => v !== arr[0] ). Bu, eşit olmayan ilk öğenin üzerine erken dönecektir arr[0].
Ocak

2
@ Jan everyda erken dönüş yapar.
golopot

111

Düzenleme: Kırmızı ninja olun:

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

Sonuçlar:

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" 

Uyarı:

var array = [] => result: TypeError thrown

Bunun nedeni bir başlangıçDeğerini geçmiyoruz . Yani, array.lengthönce kontrol etmek isteyebilirsiniz .


5
partiye biraz geç olabilir ... dizi falses yapılırsa bu işe yaramaz düşünüyorum ! örneğin, [false, false, false] .reduce (işlev (a, b) {return (a === b)? a: false;});
George Flourentzos

3
@Martin: ["false", ""]döndürür true: /
dalgard

6
Bu kullanarak bir çentik alınabilir NaN. Her ikisi de NaN === NaNve NaN !== NaNyanlış olduğundan, prevNaN olarak ayarlandıktan sonra hiçbir değerin bu değeri alamayacağını garanti eder . Ayrıca bir çift olumsuzlama ekleyerek sonuçları dönüştürür trueve falseberi NaNfalsy olduğunu. Son form:!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
Filipe Silva

3
İNDİRİLDİ . Elemanlar eşit ama sahteleyse ?
Константин Ван

3
Ben indirdim çünkü booleans değerleri ile çalışmaz.
Tyguy7

62

Bu çalışıyor. Prototip kullanarak Dizi üzerinde bir yöntem oluşturursunuz.

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

Buna şu şekilde seslenin:

let a = ['a', 'a', 'a'];
let b = a.allValuesSame(); // true
a = ['a', 'b', 'a'];
b = a.allValuesSame();     // false

5
çok güzel, ama dikkat: IE prototip atama yöntemini desteklemiyor. Zaten kullanıyorum.
Tomáš Zato - Monica adlı kişiyi geri yükle

5
@ TomášZato: IE Array.prototypeadil para cezasını arttırmayı destekler (IE6 bile). IE'nin bazı eski sürümlerinin artırmayı desteklemediği yalnızca DOM öğesi prototipleridir.
TJ Crowder

4
Ben yerleşik prototip maymun yama iyi bir fikir olduğunu sanmıyorum. Birden fazla kitaplık bunu yaparsa, hata ayıklaması çok zor olan beklenmedik davranışlara yol açabilir.
Mark Wilbur

1
@MarkWilbur 1 sonraki diziler üzerinde for..in döngüsünü yapmak, özellikle eğer sen alırsınız allValuesSamedöngüde
Olivier Pons

1
Devam ettim ve niyetini değiştirmeden bunu modernize ettim.
Bay Polywhirl

30

JavaScript 1.6'da şunları kullanabilirsiniz Array.every:

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

Muhtemelen bazı akıl sağlığı kontrollerine ihtiyacınız vardır, örneğin dizinin hiçbir elemanı olmadığında. (Ayrıca, tüm öğeler o NaNzamandan beri işe yaramaz NaN !== NaN, ancak bu bir sorun olmamalı ... değil mi?)


30

Diziyi bir Kümeye dönüştürebilirsiniz. Kümenin boyutu 1'e eşitse, Dizinin tüm öğeleri eşit olur.

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

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

Parlak. Sadece bu durumda allEqual([NaN, NaN])verir unutmayın true.
Константин Ван

12

Performans karşılaştırması için de bir kıyaslama yaptım:

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

Sonuçlar:

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)

Görünüşe göre builtin array.some () kullanmak, örneklenenlerin en hızlı yöntemidir.


3
Burada neyin daha iyi performans gösterdiğini kontrol etmek iyi bir fikir. Array#someBazen daha iyi performans göstermesinin nedeni , geri arama işlevi bir kez doğru döndüğünde yinelemeyi durdurmasıdır. Yani, eğer tüm unsurlar aslında eşitse, performans ile aynı olmalıdır Array#every. Ve tüm elemanlar eşit olmadığında göreceli performans, ilk eşleşmeyen öğenin dizinine göre değişir.
danmactough

3
Güzel bir. Her birine lol işlevini kullanarak isim vermiş olabilirsiniz. Örn: azaltmak, süzmek, her, bazı
Z. Khullah

döngü için yerli nerede, ben 5 faktörden daha iyi performans bahse girerim
PirateApp

9

Alt çizgi / lodash kullanarak en kısa cevap

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

Düzenle:

Ya da daha kısa, Tom'un cevabından esinlenerek:

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

6

Zaten underscore.js kullanıyorsanız , burada başka bir seçenek daha bulunmaktadır _.uniq:

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

_.uniqdizinin yinelenen bir sürümünü döndürür. Tüm değerler aynı ise, uzunluk 1 olacaktır.

Yorumlarda belirtildiği gibi, boş bir dizinin dönmesini beklediğiniz göz önüne alındığında, truebu durumu da kontrol etmelisiniz:

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

Ancak dizi boşsa cevabınız geri döner false. Bence öyle olmalı true. Ancak değiştirmek .length <= 1yeterli olacaktır.
ortalama Joe

@Kasztan, bu adil bir nokta. Cevabımı bu davayı kapsayacak şekilde güncelledim.
Tom Fenech

6

Evet, aşağıdaki filtreyi kullanarak da kontrol edebilirsiniz, çok basit, her değerin birinciyle aynı olduğunu kontrol edin:

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

dizideki her yöntem kullanılarak da yapılabilir:

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

ve dizilerinizi aşağıdaki gibi kontrol edebilirsiniz:

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

Ya da çok kullanıyorsanız, JavaScript'teki yerel Dizi işlevlerine ekleyebilirsiniz:

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

ve dizilerinizi aşağıdaki gibi kontrol edebilirsiniz:

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

5

Array.everyDestekleniyorsa kullanabilirsiniz :

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

Bir döngünün alternatif yaklaşımı şöyle olabilir: sort

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

Veya, öğeler soru gibi ise, kirli bir şey gibi:

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

Ayrıca çalışır.


İlk örneğiniz geriye dönük. Olmalı equals = !array.some( (v,i,a) => v!==a[0] ). Aksi takdirde, herhangi bir değerin ilkine eşit olduğunu kontrol edersiniz, ki bu her zaman doğru olacaktır :)
Mark Kahn

Tam olarak değil, kullandığım someyerine everyilk paragrafta belirtildiği gibi. :) Yakaladığınız için teşekkürler!
ZER0


3

Bunu yapmak için en basit yolu her değeri sonraki ile karşılaştırmak için bir döngü oluşturmak olduğunu düşünüyorum. "Zincir" de bir kırılma olduğu sürece yanlış dönecektir. Birincisi ikinciye, ikincisi üçüncüye eşitse, dizinin tüm öğelerinin birbirine eşit olduğu sonucuna varabiliriz.

bir dizi verisi [] verildiğinde şunu kullanabilirsiniz:

for(x=0;x<data.length - 1;x++){
    if (data[x] != data[x+1]){
        isEqual = false;            
    }
}
alert("All elements are equal is " + isEqual);

3
arr.length && arr.reduce(function(a, b){return (a === b)?a:false;}) === arr[0];

3

Yeni çözümü güncelle: dizini kontrol et

 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;

ES6 ile güncellendi: Kullanım list.everyen hızlı yoldur:

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

eski versiyon:

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

2

Bunu kullanabilirsiniz:

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

İşlev önce dizinin boş olup olmadığını kontrol eder. Değerleri eşitse .. Aksi takdirde diziyi filtreler ve ilkinden farklı olan tüm öğeleri alır. Böyle bir değer yoksa => dizi sadece eşit elemanlar içerir, aksi takdirde dizide yoktur.



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

Lütfen sadece kod yapıştırmak yerine ne yaptığınızı açıklayın.
Wouter J

1

Basit. Bir işlev oluşturun ve bir parametre iletin. Bu işlevde ilk dizini yeni bir değişkene kopyalayın. Sonra for for döngüsü oluşturun ve dizi boyunca döngü yapın. Bir döngü içinde, yeni oluşturulan değişkenin döngüdeki tüm öğelere eşit olup olmadığını kontrol eden bir koşula sahip bir while döngüsü oluşturun. for döngüsü tamamlandıktan sonra eşit dönüşü true ise while döngüsü içinde false döndürür.

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

1

Kabul edilen cevap harika çalıştı ama biraz eklemek istedim. Kullanmak benim için işe yaramadı ===çünkü nesnelerin dizilerini karşılaştırıyordum, ancak uygulamam boyunca şiddetle tavsiye ettiğim hızlı-derin eşit paketi kullanıyordum . Bununla, kodum şöyle görünür:

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

ve verilerim şöyle görünüyor:

[  
  [
    {
      "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
    }
  ]
]

1
  1. Diziye katılarak bir dize oluşturun.
  2. Verilen dizinin ilk karakterini tekrarlayarak dize oluşturma
  3. her iki dizeyle eşleş

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

Ve BİTTİ!


1

Artık bunu kolayca yapmak için setlerden faydalanabilirsiniz.

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


1

For döngüsü kullanabilirsiniz:

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

0

Bu gerçekten çok karmaşık değil. Denemediğinizden bile şüpheleniyorum. Yaptığınız şey, ilk değeri seçmeniz, değişkene kaydetmeniz ve ardından bir fordöngü içinde sonraki tüm değerleri ilk değerle karşılaştırmanızdır.
Kasıtlı olarak herhangi bir kod paylaşmadım. Nasıl forkullanıldığını ve değişkenlerin nasıl karşılaştırıldığını bulun .


8
Bu cevabı sevmiyorum. İkinci değerin üçüncü ile aynı olup olmadığını size bildirmez. Açıkça iç içe döngü bunu yapar, ancak bu kavramsal olarak acemi bir betikten farklıdır.
jtromans

3
@jtromans: eşitliğin geçişsel özelliği nedeniyle, A == B ve A == C ise B == C'yi biliyoruz; iç içe bir döngü vb. ile "manuel" olarak doğrulamanız gerekmez. Tek bir değerle karşılaştırmayı tekrarlamak (dizideki ilk değer, rastgele bir değer değil :) tam olarak bu cevabın önerdiği ve kabul edilen cevaptır.
ov

@ov Gerçekten, acelemde, o zaman bütün değerlerin eşit olduğunu (! duh) kontrol etmekten daha fazlasını gerektirdiğini düşündüğüm soruyu yanlış okudum.
jtromans

9
Karmaşık değil. Ve sayfadaki diğer cevaplar da değil. Ama bana göre, bu cevap en az yardımcı olanı.
Charlie

1
Aslında soru sormadan önce düşünmeye çalıştığı konusunda ısrarcı olan OP'ye güçlü bir nokta koymaktı.
Tomáš Zato - Monica'yı yeniden görevlendir

0

Basit bir satır çözümü, sadece ilk girişle dolu bir dizi ile karşılaştırın.

if(arr.join('') === Array(arr.length).fill(arr[0]).join(''))

Bu hiçbir yerde kullanılabilecek bir çözüm gibi görünmüyor
Lu4

Tamam oldukça yakın. Daha iyisi şöyle olur: function arrayOfSame (arr) {return (arr.join ('') == (new Array (arr.length + 1) .join (arr [0]))); }
Arkain

0

ES6 ok işlevi sözdizimini kullandığınızda başka ilginç bir yol:

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

Ve değişkeni dizi (x) için yeniden kullanmak istemediğinizde:

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

Array.every (...) kullanan önceki IMO en temiz çözüme sahiptir.


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; }
  }
}
  • İlk döngü için; düzensiz algıladığında "false" döndürür
  • İlk döngü çalışır ve false değerini döndürürse, "false"
  • Yanlış döndürülmediği zaman, doğru olacağı anlamına gelir, bu yüzden ikinci döngüyü yaparız. Ve tabii ki ikinci döngüden "true" değerine sahip olacağız (çünkü ilk döngü yanlış DEĞİL buldu)

0

Bu işe yarayabilir, aynı zamanda verilen senaryo ile de uyanır yorum kodunu kullanabilirsiniz.

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


0

Sınırlı boyut ve organize listeyle başka bir yol:

dizi1 = [1,2,3]; dizi2 = [1,2,3];

function isEqual(){

    return array1.toString()==array2.toString();
}

0

Diziyi bir Kümeye dönüştürebilir ve boyutunu kontrol edebilirsiniz

İlkel dizi girişleri durumunda, yani number, string:

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

Eşdeğerlik açısından test edilecek bir alana sahip nesnelerin dizisi durumunda, şunları söyleyin id:

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

-4

PHP'de çok basit, tek satırlık bir çözüm var:

(sayı (dizi_sayısı_değerler ($ dizi)) == 1)

Örneğin :

$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

Bu kadar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.