Проверьте, все ли значения массива равны


Мне нужно найти массивы, где все значения равны. Какой самый быстрый способ сделать это? Должен ли я перебирать его и просто сравнивать значения?

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

28 ответов:

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

или одну строчку:

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

массив.прототип.каждый (из MDN) : Метод every () проверяет, проходят ли все элементы массива тест, реализованный предоставленной функцией.

редактировать: быть красным ниндзя:

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

результаты:

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" 

предупреждение:

var array = [] => result: TypeError thrown

это потому, что мы не пройти initialValue. Таким образом, вы можете проверить array.length первый.

это работает. Вы создаете метод на массиве с помощью prototype.

Array.prototype.allValuesSame = function() {

    for(var i = 1; i < this.length; i++)
    {
        if(this[i] !== this[0])
            return false;
    }

    return true;
}

назовем это так:

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

в JavaScript 1.6, вы можете использовать Array.every:

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

вероятно, вам нужны некоторые проверки здравомыслия, например, когда массив не имеет элементов. (Кроме того, это не будет работать, когда все элементы NaN С NaN !== NaN, но это не должно быть проблемой... верно?)

вы можете превратить массив в набор. Если размер комплекта равен 1, то все элементы массива равны.

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

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

и для сравнения производительности я также сделал тест:

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

результаты:

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)

таким образом, по-видимому, используя встроенный массив.some () - это самый быстрый метод из выбранных.

самый короткий ответ с использованием подчеркивания / 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:

или даже короче, вдохновленный ответом Тома:

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

если вы уже используете подчеркивания.js, тогда вот еще один вариант с использованием _.uniq:

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

_.uniq возвращает версию массива без дубликатов. Если все значения одинаковы, то длина будет равна 1.

как уже упоминалось в комментариях, учитывая, что вы можете ожидать, что пустой массив вернет true, то вы также должны проверить для этого случая:

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

да вы можете проверить его также с помощью фильтра, как показано ниже, очень просто, проверяю все значения такие же, как и первая:

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

также можно сделать, используя каждый метод на массиве:

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

и вы можете проверить свои массивы, как показано ниже:

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

или вы можете добавить его в собственные функциональные массивы в JavaScript, если вы используете его много:

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

и вы можете проверить свои массивы, как показано ниже:

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

можно использовать Array.every при поддержке:

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

альтернативный подход цикла может быть чем-то вроде sort

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

или, если элементы, как вопрос, что-то грязное, как:

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

тоже работает.

вы можете получить этот один лайнер, чтобы сделать то, что вы хотите с помощью массив.прототип.каждый, Object.is, и ES6 стрелки функции:

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

Я думаю, что самый простой способ сделать это-создать цикл для сравнения каждого значения со следующим. Пока есть разрыв в "цепочке", то он будет возвращать false. Если первое равно второму, второе равно третьему и так далее, то можно сделать вывод, что все элементы массива равны между собой.

учитывая массив данных [], то вы можете использовать:

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

вы можете использовать это:

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

функция сначала проверяет, является ли массив пустым. Если значения равны.. В противном случае он фильтрует массив и принимает все элементы, которые отличаются от первого. Если таких значений нет => массив содержит только равные элементы, иначе это не так.

что-то вокруг этого подхода должно работать.

a.join(',').split(a[0]).length === a.length + 1

обновить новое решение: проверьте индекс

 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: Используйте list.every - Это самый быстрый способ:

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

старая версия:

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

библиотеки Underscore _.isEqual(object, other) функция, кажется, хорошо работает для массивов. Порядок элементов в массиве имеет значение, когда он проверяет равенство. См.http://underscorejs.org/#isEqual.

Ну, это действительно не очень сложно. У меня есть сильное подозрение, что ты даже не пытался. То, что вы делаете, это то, что вы выбираете первое значение, сохраняете его в переменной, а затем, в пределах for цикл, сравните все последующие значения с первым.
Я намеренно не разделял никакого кода. найти for используется и как переменные сравниваются.

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

Это Просто. Создайте функцию и передайте параметр. В этой функции скопируйте первый индекс в новую переменную. Затем создайте цикл for и цикл через массив. Внутри цикла создайте цикл while с условием, проверяющим, равна ли новая созданная переменная всем элементам в цикле. если его равный возврат true после завершения цикла for else возвращает false внутри цикла while.

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

простое однострочное решение, просто сравните его с массивом, заполненным первой записью.

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

еще один интересный способ, когда вы используете синтаксис функции стрелки 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

и когда вы не хотите повторно использовать переменную для массива (x):

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

ИМО предыдущий плакат, который использовал массив.каждый.(..) самое чистое решение.

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; }
  }
}
  • для первого цикла; всякий раз, когда он обнаруживает неравномерность, возвращает "false"
  • первый цикл выполняется, и если он возвращает false, то есть "ложные"
  • когда он не возвращает false, это означает, что будет true, поэтому мы делаем второй цикл. И, конечно же, у нас будет "true" из второго цикла (потому что первый цикл нашел, что это не ложь)

это может сработать, вы также можете использовать код комментария, который также хорошо работает с данным scenerio.

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

другой способ с разделенным размером и организованным списком:

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

function isEqual(){

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

метод every () проверяет, проходят ли все элементы в массиве тест (предоставленный как функция).

метод every () выполняет функцию один раз для каждого элемента, присутствующего в массиве:

  • если он находит элемент массива, где функция возвращает значение false value, every() возвращает false (и не проверяет остальные значения)
  • если ложь не происходит, каждый () возвращает true

Примечание: каждый() не выполняется функция для элементов массива без значений.

Примечание: every () не изменяет исходный массив

var ages = [32, 33, 16, 40];

function checkAdult(age) {
    return age == 1;
}

function myFunction() {
  alert(ages.every(checkAdult));
}
<p>Click the button to check if every element in the array is equal to one.</p>

<button onclick="myFunction()">Try it</button>
const allEqual = arr => arr.every( v => v === **arr[0]** )
allEqual( [1,1,1,1] )  // true

или одну строчку:

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

//этот код будет работать только для массива, как [1,1,1,1], [2,2,2,2] же элемент массива. Но не будет работать для [1,2,3,4]

здесь должно быть arr[i], а не arr[0]

в PHP есть решение очень простое, метод одной строки:

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

например :

$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

вот и все.