Periksa apakah semua nilai array sama

190

Saya perlu menemukan array di mana semua nilai sama. Apa cara tercepat untuk melakukan ini? Haruskah saya mengulanginya dan hanya membandingkan nilai?

['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false
Marvin3
sumber
1
@TJCrowder Saya yakin Anda sudah memikirkan solusi terbaik;)
VisioN
2
@TJCrowder: Belum lagi kesediaan penanya untuk benar-benar menerima jawaban. Pengguna dengan 1 rep sering kelihatannya tipe tanya & jalankan yang keluar segera setelah mereka memiliki jawaban yang bisa di-copy-paste, akhir-akhir ini.
Cerbrus
1
Sesuatu di sekitar pendekatan ini harusnya berhasil? a.join(',').split(a[0]).length === a.length + 1
Jashwant
1
@ TomášZato: "OP" berarti "poster asli" (orang yang mengajukan pertanyaan).
TJ Crowder

Jawaban:

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

Atau satu-liner:

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

Array.prototype.every (dari MDN): every()Metode ini menguji apakah semua elemen dalam array lulus tes yang dilaksanakan oleh fungsi yang disediakan.

golopot
sumber
11
Brevity adalah jiwa dari kecerdasan
svarog
1
Saya telah membuat case jsperf . Metode ini mengungguli sebagian besar kandidat.
Junliang Huang
1
const everythings_equal = array => array.every(thing => thing === array[0]);
Константин Ван
8
Gunakan somebukannya every: arr.some( v => v !== arr[0] ). Ini akan kembali lebih awal setelah elemen pertama ditemukan tidak setara arr[0].
Jan
2
@ Jan everytidak kembali lebih awal juga.
golopot
111

Sunting: Menjadi seorang ninja Merah:

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

Hasil:

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" 

Peringatan:

var array = [] => result: TypeError thrown

Ini karena kami tidak melewati Nilai awal . Jadi, Anda mungkin ingin memeriksa array.lengthdulu.

Martin
sumber
5
mungkin agak terlambat ke pesta ... saya pikir ini tidak berfungsi jika array Anda terbuat dari falses! misalnya coba [false, false, false] .reduce (function (a, b) {return (a === b)? a: false;});
George Flourentzos
3
@ Martin: ["false", ""]mengembalikan true: /
dalgard
6
Ini bisa diambil takik dengan menggunakan NaN. Karena keduanya NaN === NaNdan NaN !== NaNsalah, itu menjamin bahwa setelah prevdiatur ke NaN maka tidak ada nilai yang bisa mengeluarkannya. Juga menambahkan negasi ganda mengubah hasil menjadi truedan false, karena NaNitu palsu. Bentuk akhir:!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
Filipe Silva
3
DIUNDUH . Bagaimana jika elemen-elemennya sama tetapi palsu ?
Константин Ван
3
Saya downvoted karena ini tidak bekerja dengan nilai-nilai boolean.
Tyguy7
62

Ini bekerja. Anda membuat metode pada Array dengan menggunakan prototipe.

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

Panggil ini dengan cara ini:

let a = ['a', 'a', 'a'];
let b = a.allValuesSame(); // true
a = ['a', 'b', 'a'];
b = a.allValuesSame();     // false
Robert Fricke
sumber
5
sangat bagus, tetapi berhati-hatilah: IE tidak mendukung cara penetapan prototipe ini. Saya tetap menggunakannya.
Tomáš Zato - Reinstate Monica
5
@ TomášZato: IE mendukung penambahan Array.prototypebaik-baik saja (bahkan IE6). Ini hanya prototipe elemen DOM bahwa beberapa versi IE yang lebih lama tidak mendukung penambahan.
TJ Crowder
4
Saya tidak berpikir itu ide yang baik untuk menjadi prototipe built-in monyet patch. Jika banyak pustaka melakukannya, itu dapat menyebabkan perilaku tak terduga yang sangat sulit untuk di-debug.
Mark Wilbur
1
@ MarkWilbur +1 terutama jika Anda melakukan for..in loop pada array berikutnya, Anda akan mendapatkan allValuesSamedalam loop
Olivier Pons
1
Saya teruskan dan memodernisasi ini, tanpa mengubah niat.
Tn. Polywhirl
30

Di JavaScript 1.6, Anda dapat menggunakan Array.every:

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

Anda mungkin memerlukan beberapa pemeriksaan kewarasan, misalnya ketika array tidak memiliki elemen. (Juga, ini tidak akan berfungsi ketika semua elemen NaNsejak itu NaN !== NaN, tapi itu seharusnya tidak menjadi masalah ... kan?)

Mattias Buelens
sumber
30

Anda dapat mengubah Array menjadi Set. Jika ukuran Set sama dengan 1, maka semua elemen dari Array sama.

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

allEqual(['a', 'a', 'a', 'a']); // true
allEqual(['a', 'a', 'b', 'a']); // false
Huy Tran
sumber
Cemerlang. Perhatikan saja yang allEqual([NaN, NaN])memberi truedalam kasus ini.
Константин Ван
12

Dan untuk perbandingan kinerja saya juga melakukan 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];
    });
}

Hasil:

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)

Jadi ternyata menggunakan builtin array.some () adalah metode tercepat dari yang disampel.

Martin
sumber
3
Ide bagus untuk memeriksa apa yang lebih performant di sini. Alasan mengapa Array#somekadang-kadang mengungguli adalah bahwa begitu fungsi callback kembali benar, itu berhenti iterasi. Jadi, jika semua elemen pada kenyataannya sama, kinerja harus identik dengan Array#every. Dan kinerja relatif ketika semua elemen tidak sama akan bervariasi berdasarkan indeks elemen tidak cocok pertama.
danmactough
3
Bagus Anda bisa memberi nama masing-masing dengan fungsi yang digunakan lol. Misalnya: kurangi, filter, setiap, sebagian
Z. Khullah
di mana asli untuk loop, saya yakin itu mengungguli semua ini dengan faktor 5
PirateApp
9

Jawaban terpendek menggunakan garis bawah / 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

edit:

Atau bahkan lebih pendek, terinspirasi oleh jawaban 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
rata-rata Joe
sumber
6

Jika Anda sudah menggunakan underscore.js , maka inilah opsi lain menggunakan _.uniq:

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

_.uniqmengembalikan versi larik duplikat. Jika semua nilainya sama, maka panjangnya adalah 1.

Seperti yang disebutkan dalam komentar, mengingat Anda mungkin mengharapkan array kosong untuk kembali true, maka Anda juga harus memeriksa kasus itu:

function allEqual(arr) {
    return arr.length === 0 || _.uniq(arr).length === 1;
}
Tom Fenech
sumber
Tetapi jika array kosong, jawaban Anda akan kembali false. Sementara saya pikir seharusnya begitu true. Mengubah ke .length <= 1akan cukup.
Rata
@Kasztan itu poin yang adil. Saya telah memperbarui jawaban saya untuk membahas hal itu.
Tom Fenech
6

Ya, Anda dapat memeriksanya juga menggunakan filter seperti di bawah ini, sangat sederhana, memeriksa setiap nilai sama dengan yang pertama:

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

juga dapat dilakukan dengan menggunakan setiap metode pada array:

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

dan Anda dapat memeriksa array Anda seperti di bawah ini:

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

Atau Anda dapat menambahkannya ke fungsionalitas Array asli dalam JavaScript jika Anda sering menggunakannya kembali:

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

dan Anda dapat memeriksa array Anda seperti di bawah ini:

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

Anda dapat menggunakan Array.everyjika didukung:

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

Pendekatan alternatif dari sebuah loop bisa berupa sesuatu sort

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

Atau, jika barang seperti pertanyaan, sesuatu yang kotor seperti:

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

Juga berfungsi.

ZER0
sumber
Anda memiliki contoh pertama mundur. Seharusnya equals = !array.some( (v,i,a) => v!==a[0] ). Kalau tidak, Anda hanya memeriksa bahwa nilai apa pun sama dengan nilai pertama yang, tentu saja, selalu benar :)
Mark Kahn
Tidak persis, saya menggunakan somebukannya everyseperti yang saya sebutkan di paragraf pertama. :) Terima kasih atas tangkapannya!
ZER0
5

Anda bisa mendapatkan one-liner ini untuk melakukan apa yang Anda inginkan menggunakan fungsi panah Array.prototype.every , Object.is , dan ES6:

const all = arr => arr.every(x => Object.is(arr[0], x));
Noor
sumber
2
Tolong, jelaskan solusi yang Anda usulkan.
il_raffa
3

Saya pikir cara paling sederhana untuk melakukan ini adalah dengan membuat loop untuk membandingkan setiap nilai ke yang berikutnya. Selama ada istirahat dalam "rantai" maka itu akan kembali salah. Jika yang pertama sama dengan yang kedua, yang kedua sama dengan yang ketiga dan seterusnya, maka kita dapat menyimpulkan bahwa semua elemen array sama satu sama lain.

diberi data array [], maka Anda dapat menggunakan:

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

Perbarui solusi baru: periksa 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;

Diperbarui dengan ES6: Penggunaan list.everyadalah cara tercepat:

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

versi lama:

      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
sumber
2

Anda bisa menggunakan ini:

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

Fungsi pertama-tama memeriksa apakah array kosong. Jika itu nilainya sama dengan .. Kalau tidak, filter array dan mengambil semua elemen yang berbeda dari yang pertama. Jika tidak ada nilai seperti itu => array hanya berisi elemen yang sama jika tidak, maka array tersebut tidak.

Minko Gechev
sumber
1

_.isEqual(object, other)Fungsi garis bawah tampaknya berfungsi dengan baik untuk array. Urutan item dalam array penting saat memeriksa kesetaraan. Lihat http://underscorejs.org/#isEqual .

Jon Onstott
sumber
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);
    }));
}
pengguna4861889
sumber
Tolong juga jelaskan apa yang Anda lakukan alih-alih hanya menempelkan beberapa kode.
Wouter J
1

Itu mudah. Buat fungsi dan berikan parameter. Dalam fungsi itu salin indeks pertama ke variabel baru. Kemudian Buat loop untuk dan loop melalui array. Di dalam loop membuat loop sementara dengan kondisi memeriksa apakah variabel yang baru dibuat sama dengan semua elemen dalam loop. jika pengembaliannya sama dengan true setelah for loop selesai, kembali false di dalam while loop.

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

The jawaban yang diterima bekerja hebat tapi saya ingin menambahkan sedikit. Itu tidak berfungsi untuk saya gunakan ===karena saya membandingkan array array objek, namun di seluruh aplikasi saya, saya telah menggunakan paket fast-deep-equal yang sangat saya rekomendasikan. Dengan itu, kode saya terlihat seperti ini:

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

dan data saya terlihat seperti ini:

[  
  [
    {
      "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
sumber
1
  1. Buat string dengan bergabung dengan array.
  2. Buat string dengan pengulangan karakter pertama dari array yang diberikan
  3. cocok dengan kedua string

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

Dan kamu DILAKUKAN!

Rahul Vala
sumber
1

Sekarang Anda dapat menggunakan set untuk melakukannya dengan mudah.

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

Anda bisa menggunakan for 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
sumber
0

Nah, ini sebenarnya tidak terlalu rumit. Saya memiliki kecurigaan yang kuat bahwa Anda bahkan tidak mencoba. Apa yang Anda lakukan adalah bahwa Anda memilih nilai pertama, menyimpannya dalam variabel, dan kemudian, dalam satu forlingkaran, bandingkan semua nilai berikutnya dengan yang pertama.
Saya sengaja tidak membagikan kode apa pun. Temukan bagaimana fordigunakan dan bagaimana variabel dibandingkan.

Tomáš Zato - Pasang kembali Monica
sumber
8
Saya tidak suka jawaban ini. Itu tidak akan memberi tahu Anda jika nilai kedua sama dengan yang ketiga, dll. Jelas nested loop akan melakukannya, tetapi itu secara konseptual berbeda dengan skrip pemula.
jtromans
3
@ jtromans: karena properti transitif dari kesetaraan, jika A == B dan A == C maka kita tahu B == C; Anda tidak harus memverifikasinya "secara manual" dengan loop bersarang dll. Mengulangi perbandingan terhadap nilai tunggal (nilai pertama dalam array, bukan yang sewenang-wenang :) persis seperti yang disarankan jawaban ini dan begitu juga jawaban yang diterima.
Ov
@ov Memang, dengan tergesa-gesa saya salah membaca pertanyaan, yang saya pikir pada saat itu diperlukan lebih dari sekadar memeriksa bahwa semua nilai sama (! duh).
jtromans
9
Itu tidak rumit. Dan tidak ada jawaban lain di halaman. Tetapi bagi saya, jawaban ini sejauh ini paling tidak membantu.
Charlie
1
Ini awalnya dimaksudkan untuk membuat poin kuat ke OP bersikeras dia mencoba berpikir sebelum mengajukan pertanyaan.
Tomáš Zato - Reinstate Monica
0

Solusi satu baris yang sederhana, bandingkan saja dengan array yang diisi dengan entri pertama.

if(arr.join('') === Array(arr.length).fill(arr[0]).join(''))
pyviet
sumber
Itu tidak tampak seperti solusi yang dapat digunakan di mana saja
Lu4
Cukup dekat dengan ok. Lebih baik berupa: function arrayOfSame (arr) {return (arr.join ('') == (Array baru (arr.length + 1) .join (arr [0]))); }
Arkain
0

Cara lain yang menarik ketika Anda menggunakan sintaks fungsi panah 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

Dan ketika Anda tidak ingin menggunakan kembali variabel untuk array (x):

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

Poster IMO sebelumnya yang menggunakan array.every (...) memiliki solusi terbersih.

Tomasz Szawara
sumber
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; }
  }
}
  • Untuk loop pertama; setiap kali terdeteksi tidak rata, kembalikan "false"
  • Loop pertama berjalan, dan jika mengembalikan false, kita memiliki "false"
  • Ketika itu tidak mengembalikan false, itu berarti akan ada benar, jadi kami melakukan loop kedua. Dan tentu saja kita akan memiliki "true" dari loop kedua (karena loop pertama menemukan itu TIDAK salah)
Jaden Tran
sumber
0

ini mungkin bekerja, Anda dapat menggunakan kode komentar juga yang juga baik dengan scenerio yang diberikan.

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

Cara lain dengan ukuran terbatas dan daftar terorganisir:

array1 = [1,2,3]; array2 = [1,2,3];

function isEqual(){

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

Anda dapat mengubah array menjadi Set dan memeriksa ukurannya

Dalam kasus entri array yang primitif, yaitu number, string:

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

Dalam kasus array objek dengan beberapa bidang yang akan diuji untuk kesetaraan, katakan id:

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

Di PHP, ada solusi yang sangat sederhana, metode satu baris:

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

Sebagai contoh :

$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

Itu saja.

Jerry
sumber