Kiểm tra xem tất cả các giá trị của mảng có bằng nhau không


188

Tôi cần tìm các mảng trong đó tất cả các giá trị bằng nhau. Cách nhanh nhất để làm điều này là gì? Tôi có nên lặp qua nó và chỉ so sánh các giá trị?

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

1
@TJCrowder Tôi cá là bạn đã nghĩ về giải pháp tốt nhất;)
VisioN

2
@TJCrowder: Chưa kể đến sự sẵn lòng của người hỏi để thực sự chấp nhận câu trả lời. Người dùng có 1 đại diện dường như thường hỏi và chạy các loại rời khỏi ngay khi họ có câu trả lời có thể sao chép-dán, gần đây.
Cerbrus

1
Một cái gì đó xung quanh phương pháp này nên làm việc? a.join(',').split(a[0]).length === a.length + 1
Jashwant

1
@ TomášZato: "OP" có nghĩa là "áp phích gốc" (người đặt câu hỏi).
TJ Crowder

Câu trả lời:


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

Hoặc một lớp lót:

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

Array.prototype.every (từ MDN): every()Phương thức kiểm tra xem tất cả các phần tử trong mảng có vượt qua kiểm tra được thực hiện bởi hàm được cung cấp hay không.


10
Brevity là linh hồn của trí thông minh
svarog

1
Tôi đã tạo ra một trường hợp jsperf . Phương pháp này tốt hơn hầu hết các ứng cử viên.
Junliang Huang

1
const everythings_equal = array => array.every(thing => thing === array[0]);
Toàn cảnh

8
Sử dụng somethay vì every: arr.some( v => v !== arr[0] ). Điều này sẽ trở lại sớm khi yếu tố đầu tiên được tìm thấy là không đồng đều arr[0].
ngày

2
@Jan everycũng sớm trở về.
golopot

111

Chỉnh sửa: Trở thành ninja đỏ:

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

Các kết quả:

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" 

Cảnh báo:

var array = [] => result: TypeError thrown

Điều này là do chúng ta không vượt qua một initialValue . Vì vậy, bạn có thể muốn kiểm tra array.lengthđầu tiên.


5
có thể là một chút muộn cho bữa tiệc ... tôi nghĩ rằng điều này không hoạt động nếu mảng của bạn được làm bằng falses! ví dụ thử [false, false, false] .reduce (function (a, b) {return (a === b)? a: false;});
George Flourentzos

3
@Martin: ["false", ""]trả về true: /
dachard

6
Điều này có thể được đưa lên một notch bằng cách sử dụng NaN. Vì cả hai NaN === NaNNaN !== NaNđều sai, nó đảm bảo rằng một khi prevđược đặt thành NaN thì không có giá trị nào có thể lấy nó ra. Ngoài ra, thêm vào một phủ định kép sẽ chuyển đổi kết quả thành truefalse, vì NaNlà sai. Hình thức cuối cùng:!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
Filipe Silva

3
TẢI XUỐNG . Điều gì nếu các yếu tố đều bình đẳng nhưng falsy ?
Toàn cảnh

3
Tôi đã bỏ qua vì điều này không hoạt động với các giá trị booleans.
Tyguy7

62

Những công việc này. Bạn tạo một phương thức trên Array bằng cách sử dụng nguyên mẫu.

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

Gọi đây theo cách này:

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

5
rất hay, nhưng hãy cẩn thận: IE không hỗ trợ cách gán nguyên mẫu này. Tôi sử dụng nó anyway.
Tomáš Zato - Phục hồi Monica

5
@ TomášZato: IE hỗ trợ tăng cường Array.prototypetốt (thậm chí IE6). Đây chỉ là các nguyên mẫu phần tử DOM mà một số phiên bản IE cũ hơn không hỗ trợ tăng cường.
TJ Crowder

4
Tôi không nghĩ rằng đó là một ý tưởng tốt để khỉ vá các nguyên mẫu tích hợp. Nếu nhiều thư viện làm điều đó, nó có thể dẫn đến hành vi không mong muốn rất khó gỡ lỗi.
Đánh dấu Wilbur

1
@MarkWilbur +1 đặc biệt nếu bạn thực hiện vòng lặp for..in trên các mảng tiếp theo, bạn sẽ allValuesSamevào vòng lặp
Olivier Pons

1
Tôi đã đi trước và hiện đại hóa điều này, mà không thay đổi ý định.
Ông Polywhirl

30

Trong JavaScript 1.6, bạn có thể sử dụng Array.every:

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

Bạn có thể cần một số kiểm tra độ tỉnh táo, ví dụ khi mảng không có phần tử. (Ngoài ra, điều này sẽ không hoạt động khi tất cả các yếu tố NaNkể từ đó NaN !== NaN, nhưng đó không phải là vấn đề ... phải không?)


30

Bạn có thể biến Mảng thành Tập hợp. Nếu kích thước của Tập hợp bằng 1, thì tất cả các phần tử của Mảng đều bằng nhau.

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

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

Xuất sắc. Chỉ cần lưu ý rằng allEqual([NaN, NaN])đưa ra truetrong trường hợp này.
Toàn cảnh

12

Và để so sánh hiệu suất tôi cũng đã làm một điểm chuẩn:

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

Các kết quả:

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)

Vì vậy, rõ ràng bằng cách sử dụng hàm dựng sẵn Array.some () là phương thức nhanh nhất được lấy mẫu.


3
Ý tưởng tốt để kiểm tra những gì hiệu quả hơn ở đây. Lý do tại sao Array#someđôi khi sẽ tốt hơn là một khi chức năng gọi lại trả về đúng, nó dừng lặp lại. Vì vậy, nếu tất cả các yếu tố trên thực tế là bằng nhau, hiệu suất nên giống hệt nhau Array#every. Và hiệu suất tương đối khi tất cả các yếu tố không bằng nhau sẽ thay đổi dựa trên chỉ số của yếu tố không phù hợp đầu tiên.
danmactough

3
Đẹp một. Bạn có thể đặt tên cho mỗi với chức năng được sử dụng lol. Ví dụ: giảm, lọc, mọi, một số
Z. Khullah

Vòng lặp gốc ở đâu, tôi cá rằng nó vượt trội hơn tất cả những thứ này theo hệ số 5
PirateApp

9

Câu trả lời ngắn nhất bằng cách sử dụng dấu gạch dưới / lodash

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

thông số kỹ thuật:

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

biên tập:

Hoặc thậm chí ngắn hơn, lấy cảm hứng từ câu trả lời của Tom:

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

thông số kỹ thuật:

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

6

Nếu bạn đã sử dụng underscore.js , thì đây là một tùy chọn khác sử dụng _.uniq:

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

_.uniqtrả về một phiên bản không có bản sao của mảng. Nếu tất cả các giá trị là như nhau, thì độ dài sẽ là 1.

Như đã đề cập trong các bình luận, cho rằng bạn có thể mong đợi một mảng trống trở lại true, thì bạn cũng nên kiểm tra trường hợp đó:

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

Nhưng nếu mảng trống, câu trả lời của bạn sẽ trở lại false. Trong khi tôi nghĩ nó nên như vậy true. Thay đổi thành .length <= 1sẽ là đủ mặc dù.
trung bình Joe

@Kasztan đó là một điểm công bằng. Tôi đã cập nhật câu trả lời của mình để giải quyết trường hợp đó.
Tom Fenech

6

Có, bạn có thể kiểm tra nó bằng cách sử dụng bộ lọc như dưới đây, rất đơn giản, kiểm tra mọi giá trị giống như giá trị đầu tiên:

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

cũng có thể được thực hiện bằng cách sử dụng mọi phương thức trên mảng:

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

và bạn có thể kiểm tra mảng của mình như dưới đây:

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

Hoặc bạn có thể thêm nó vào các chức năng Mảng bản địa trong JavaScript nếu bạn sử dụng lại nhiều:

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

và bạn có thể kiểm tra mảng của mình như dưới đây:

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

5

Bạn có thể sử dụng Array.everynếu được hỗ trợ:

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

Cách tiếp cận thay thế của một vòng lặp có thể là một cái gì đó như sort

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

Hoặc, nếu các mục giống như câu hỏi, một cái gì đó bẩn như:

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

Cũng hoạt động.


Bạn có ví dụ đầu tiên ngược. Nên equals = !array.some( (v,i,a) => v!==a[0] ). Mặt khác, bạn chỉ kiểm tra xem bất kỳ giá trị nào bằng giá trị đầu tiên, tất nhiên, sẽ luôn luôn đúng :)
Mark Kahn

Không chính xác, tôi đã sử dụng somethay vì everynhư tôi đã đề cập trong đoạn đầu tiên. :) Cảm ơn đã bắt!
ZER0

5

Bạn có thể có được một lớp lót này để làm những gì bạn muốn bằng cách sử dụng các hàm mũi tên Array.prototype.every , Object.is và ES6:

const all = arr => arr.every(x => Object.is(arr[0], x));

2
Xin vui lòng, mô tả các giải pháp bạn đang đề xuất.
il_raffa

3

Tôi nghĩ cách đơn giản nhất để làm điều này là tạo một vòng lặp để so sánh từng giá trị với giá trị tiếp theo. Chừng nào có sự phá vỡ trong "chuỗi" thì nó sẽ trả về false. Nếu cái thứ nhất bằng cái thứ hai, cái thứ hai bằng cái thứ ba và cứ thế, thì chúng ta có thể kết luận rằng tất cả các phần tử của mảng đều bằng nhau.

đưa ra một dữ liệu mảng [], sau đó bạn có thể sử dụng:

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

Cập nhật giải pháp mới: kiểm tra chỉ số

 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;

Cập nhật với ES6: Sử dụng list.everylà cách nhanh nhất:

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

phiên bản cũ:

      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

Bạn có thể sử dụng điều này:

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

Hàm đầu tiên kiểm tra xem mảng có trống không. Nếu đó là giá trị của nó bằng nhau .. Nếu không, nó lọc mảng và lấy tất cả các phần tử khác với phần tử đầu tiên. Nếu không có giá trị nào như vậy => mảng chỉ chứa các phần tử bằng nhau thì không.



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

Vui lòng giải thích những gì bạn đã làm thay vì chỉ dán một số mã.
Wouter J

1

Nó đơn giản. Tạo một hàm và truyền tham số. Trong chức năng đó sao chép chỉ mục đầu tiên vào một biến mới. Sau đó, tạo một vòng lặp for và lặp qua mảng. Bên trong một vòng lặp tạo một vòng lặp while với một điều kiện kiểm tra xem biến được tạo mới có bằng tất cả các phần tử trong vòng lặp hay không. nếu trả về bằng của nó đúng sau khi vòng lặp for hoàn thành thì trả về false bên trong vòng lặp while.

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

1

Các câu trả lời được chấp nhận làm việc rất lớn nhưng tôi muốn thêm một chút. Nó không hoạt động đối với tôi ===vì tôi đang so sánh các mảng của các đối tượng, tuy nhiên trong suốt ứng dụng của tôi, tôi đã sử dụng gói nhanh ngang bằng mà tôi rất khuyến khích. Với điều đó, mã của tôi trông như thế này:

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

và dữ liệu của tôi trông như thế này:

[  
  [
    {
      "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. Tạo một chuỗi bằng cách tham gia mảng.
  2. Tạo chuỗi bằng cách lặp lại ký tự đầu tiên của mảng đã cho
  3. nối cả hai chuỗi

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

Và bạn đang làm!


1

Bây giờ bạn có thể sử dụng các bộ để làm điều đó một cách dễ dàng.

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

Bạn có thể sử dụng vòng lặp for:

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

0

Vâng, điều này thực sự không phức tạp lắm. Tôi có sự nghi ngờ mạnh mẽ mà bạn thậm chí không thử. Những gì bạn làm là bạn chọn giá trị đầu tiên, lưu nó vào biến và sau đó, trong một forvòng lặp, so sánh tất cả các giá trị tiếp theo với giá trị đầu tiên.
Tôi cố tình không chia sẻ bất kỳ mã. Tìm cách forsử dụng và cách so sánh các biến.


8
Tôi không thích câu trả lời này. Nó sẽ không cho bạn biết nếu giá trị thứ hai giống với giá trị thứ ba, v.v ... Rõ ràng vòng lặp lồng nhau sẽ làm điều đó, nhưng về mặt khái niệm thì khác với một người viết kịch bản mới.
jtromans

3
@jtromans: vì tính chất bắc cầu của đẳng thức, nếu A == B và A == C thì ta biết B == C; bạn không phải xác minh "thủ công" bằng một vòng lặp lồng nhau, v.v. Lặp lại so sánh với một giá trị duy nhất (giá trị đầu tiên trong mảng, không phải là tùy ý :) chính xác là câu trả lời này cho thấy câu trả lời được chấp nhận.
trứng

@ov Thật vậy, trong sự vội vàng của mình, tôi đã đọc sai câu hỏi, điều mà tôi nghĩ lúc đó cần nhiều hơn là chỉ kiểm tra rằng tất cả các giá trị đều bằng nhau (! duh).
jtromans

9
Nó không phức tạp. Và không có câu trả lời khác trên trang. Nhưng với tôi, câu trả lời này là ít hữu ích nhất.
Charlie

1
Ban đầu nó có nghĩa là để tạo ra một điểm mạnh đối với OP khăng khăng rằng anh ta cố gắng suy nghĩ trước khi đặt câu hỏi.
Tomáš Zato - Phục hồi Monica

0

Giải pháp một dòng đơn giản, chỉ cần so sánh nó với một mảng chứa đầy mục nhập đầu tiên.

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

Đó dường như không phải là một giải pháp có thể được sử dụng ở bất cứ đâu
Lu4

Nó khá gần với ok. Tốt hơn sẽ là một cái gì đó như: function ArrayOfSame (Array) {return (Array.join ('') == (new Array (Array.length + 1) .join (Array [0]))); }
Arkain 15/03/2017

0

Một cách thú vị khác khi bạn sử dụng cú pháp hàm mũi tên 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

Và khi bạn không muốn sử dụng lại biến cho mảng (x):

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

Áp phích trước của IMO, người đã sử dụng mảng.every (...) có giải pháp sạch nhất.


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; }
  }
}
  • Đối với vòng lặp đầu tiên; Bất cứ khi nào nó phát hiện không đồng đều, trả về "false"
  • Vòng lặp đầu tiên chạy và nếu nó trả về false, chúng ta có "false"
  • Khi nó không trả về false, điều đó có nghĩa là sẽ đúng, vì vậy chúng tôi thực hiện vòng lặp thứ hai. Và tất nhiên chúng ta sẽ có "true" từ vòng lặp thứ hai (vì vòng lặp thứ nhất thấy nó KHÔNG sai)

0

điều này có thể hoạt động, bạn có thể sử dụng mã nhận xét cũng phù hợp với scenerio đã cho.

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

Một cách khác với kích thước phân cách và danh sách có tổ chức:

mảng1 = [1,2,3]; mảng2 = [1,2,3];

function isEqual(){

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

0

Bạn có thể chuyển đổi mảng thành Tập hợp và kiểm tra kích thước của nó

Trong trường hợp các mục mảng nguyên thủy, tức là number, string:

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

Trong trường hợp mảng các đối tượng với một số trường được kiểm tra tương đương, hãy nói id:

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

-4

Trong PHP, có một giải pháp rất đơn giản, phương thức một dòng:

(đếm (mảng_count_values ​​($ mảng)) == 1)

Ví dụ :

$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

Đó là tất cả.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.