Проверьте, все ли значения массива равны
Мне нужно найти массивы, где все значения равны. Какой самый быстрый способ сделать это? Должен ли я перебирать его и просто сравнивать значения?
['a', 'a', 'a', 'a'] // true
['a', 'a', 'b', 'a'] // false
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);
вы можете использовать это:
function same(a) { if (!a.length) return true; return !a.filter(function (e) { return e !== a[0]; }).length; }
функция сначала проверяет, является ли массив пустым. Если значения равны.. В противном случае он фильтрует массив и принимает все элементы, которые отличаются от первого. Если таких значений нет => массив содержит только равные элементы, иначе это не так.
обновить новое решение: проверьте индекс
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
вот и все.