Как узнать, имеют ли два массива одинаковые значения
У меня есть эти два массива: один заполняется информацией из запроса ajax, а другой хранит кнопки, на которые пользователь нажимает. Я использую этот код (заполненный номерами примеров):
var array1 = [2, 4];
var array2 = [4, 2]; //It cames from the user button clicks, so it might be disordered.
array1.sort(); //Sorts both Ajax and user info.
array2.sort();
if (array1==array2) {
doSomething();
}else{
doAnotherThing();
}
Но он всегда дает false
, даже если оба массива одинаковы, но с другим именем. (Я проверил это в консоли Chrome JS). Итак, можно ли каким-либо образом узнать, содержат ли эти два массива одно и то же? Почему он дает false
? Как узнать, какие значения в первом массиве находятся не во втором?
Ответы
Ответ 1
function arraysEqual(_arr1, _arr2) {
if (!Array.isArray(_arr1) || ! Array.isArray(_arr2) || _arr1.length !== _arr2.length)
return false;
var arr1 = _arr1.concat().sort();
var arr2 = _arr2.concat().sort();
for (var i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i])
return false;
}
return true;
}
Обратите внимание, что это не изменяет исходные массивы в отличие от предыдущего ответа.
Ответ 2
Если ваши элементы массива не являются объектами - например, это числа или строки, вы можете сравнить их объединенные строки, чтобы увидеть, имеют ли они одни и те же члены в любом порядке -
var array1= [10, 6, 19, 16, 14, 15, 2, 9, 5, 3, 4, 13, 8, 7, 1, 12, 18, 11, 20, 17];
var array2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];
if(array1.sort().join(',')=== array2.sort().join(',')){
alert('same members');
}
else alert('not a match');
Ответ 3
Array.prototype.compare = function(testArr) {
if (this.length != testArr.length) return false;
for (var i = 0; i < testArr.length; i++) {
if (this[i].compare) { //To test values in nested arrays
if (!this[i].compare(testArr[i])) return false;
}
else if (this[i] !== testArr[i]) return false;
}
return true;
}
var array1 = [2, 4];
var array2 = [4, 2];
if(array1.sort().compare(array2.sort())) {
doSomething();
} else {
doAnotherThing();
}
Может быть?
Ответ 4
Если вы хотите проверить, только если два массива имеют одинаковые значения (независимо от количества вхождений и порядка каждого значения), вы можете сделать это, используя lodash:
_.isEmpty(_.xor(array1, array2))
Короткий, простой и красивый!
Ответ 5
Почему ваш код не работает
JavaScript имеет примитивные типы данных и непримитивные типы данных.
Для примитивных типов данных ==
и ===
проверьте, имеют ли вещи по обе стороны от баров одинаковое значение. Вот почему 1 === 1
истинно.
Для не-примитивных типов данных, таких как массивы, ==
и ===
проверьте ссылочное равенство. То есть, они проверяют, являются ли теги arr1
и arr2
одним и тем же объектом. В вашем примере два массива имеют одни и те же объекты в одном порядке, но не эквивалентны.
Решение
Два массива, arr1
и arr2
, имеют одинаковые элементы тогда и только тогда, когда:
- Все в
arr2
находится в arr1
и
- Все в
arr1
находится в arr2
Итак, это сделает трюк (ES2016):
const containsAll = (arr1, arr2) =>
arr2.every(arr2Item => arr1.includes(arr2Item))
const sameMembers = (arr1, arr2) =>
containsAll(arr1, arr2) && containsAll(arr2, arr1);
sameMembers(arr1, arr2); // `true`
Это второе решение, использующее Underscore, ближе к тому, что вы пытались сделать:
arr1.sort();
arr2.sort();
_.isEqual(arr1, arr2); // `true`
Это работает, потому что isEqual
проверяет "глубокое равенство", что означает, что он смотрит не только на ссылочное равенство и сравнивает значения.
Решение третьего вопроса
Вы также спросили, как узнать, какие вещи в arr1
не содержатся в arr2
.
Это сделает это (ES2015):
const arr1 = [1, 2, 3, 4];
const arr2 = [3, 2, 1];
arr1.filter(arr1Item => !arr2.includes(arr1Item)); // `[4]`
Вы также можете использовать Underscore difference
: method:
_.difference(arr1, arr2); // `[4]`
UPDATE
См. комментарий @Redu. Мое решение для sameMembers
, но вы можете иметь в виду sameMembersInOrder
, также известный как deepEquals
.
ОБНОВЛЕНИЕ 2
Если вы не заботитесь о порядке членов массивов, ES2015 + Set
может быть лучшей структурой данных, чем Array
. См. примечания MDN о том, как реализовать isSuperset
и difference
, используя опасные исправления обезьян.
Ответ 6
Проверка равенства объектов: JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())
Вышеупомянутый тест также работает с массивами объектов, в этом случае используется функция сортировки, как описано в http://www.w3schools.com/jsref/jsref_sort.asp
Может быть достаточно для небольших массивов с плоскими схемами JSON.
Ответ 7
Когда вы сравниваете эти два массива, вы сравниваете объекты, представляющие массивы, а не содержимое.
Вам нужно будет использовать функцию для сравнения двух. Вы можете написать свой собственный, который просто петли, хотя один, и сравнивает его с другим после того, как вы проверите, что длины одинаковы.
Ответ 8
Наша цель в основном проверить, равны ли 2 массива. Здесь множество означает математическое множество. Самая быстрая сортировка асимптотически занимает время O (nlog (n)). Вы можете сделать это асимптотически O (n) раз со структурой данных словаря. В JS словарь - это просто объект с ключами и значениями.
// assumes array elements are primitive types
function areArraysEqualSets(a1, a2) {
let superSet = {};
for (let i = 0; i < a1.length; i++) {
const e = a1[i] + typeof a1[i];
superSet[e] = 1;
}
for (let i = 0; i < a2.length; i++) {
const e = a2[i] + typeof a2[i];
if (!superSet[e]) {
return false;
}
superSet[e] = 2;
}
for (let e in superSet) {
if (superSet[e] === 1) {
return false;
}
}
return true;
}
Обратите внимание, что эта функция работает с массивами примитивных типов и предполагает, что a1 и a2 являются массивами
Ответ 9
Если вы используете Prototype Framework, вы можете использовать метод intersect массива, чтобы узнать, что они одинаковы ( независимо от порядка):
var array1 = [1,2];
var array2 = [2,1];
if(array1.intersect(array2).length === array1.length) {
alert("arrays are the same!");
}
Ответ 10
У меня были простые целочисленные значения в проекте игры
Если бы меньшее количество значений в каждом массиве также нуждалось в том, что исходный массив не затронут
Итак, я сделал это ниже, он работал нормально. (Код отредактирован для вставки здесь)
var sourceArray = [1, 2, 3];
var targetArray = [3, 2, 1];
if (sourceArray.length !== targetArray.length) {
// not equal
// did something
return false;
}
var newSortedSourceArray = sourceArray.slice().sort();
var newSortedTargetArray = targetArray.slice().sort();
if (newSortedSourceArray.toString() !== newSortedTargetArray.toString()) { // MAIN CHECK
// not equal
// did something
return false;
}
else {
// equal
// did something
// continued further below
}
// did some more work
return true;
Надеюсь, что это поможет.
Ответ 11
Использование ES6
Мы будем использовать функцию equals
Ramda, но вместо этого мы можем использовать Lodash или Underscore isEqual
:
const R = require('ramda');
const arraysHaveSameValues = (arr1, arr2) => R.equals( [...arr1].sort(), [...arr2].sort() )
Используя противодействие распространению, мы избегаем изменения оригинальных массивов и сохраняем нашу функцию чистой.
Ответ 12
любезно проверьте этот ответ
var arr1= [12,18];
var arr2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];
for(i=0;i<arr1.length;i++)
{
var array1=arr1[i];
for(j=0;j<arr2.length;j++)
{
var array2=arr2[j];
if(array1==array2)
{
return true;
}
}
}
Ответ 13
Если элементы в массиве являются примитивами (числами или одиночными символами), вы можете использовать комбинацию сравнения длин и использования наборов.
function equalArrayItems(arr1, arr2) {
if (arr1.length !== arr2.length) return false
const set1 = new Set(arr1)
const set2 = new Set(arr2)
const set3 = new Set(arr1, arr2)
return set1.size === set3.size && set2.size === set3.size
}
Ответ 14
Отвечая через долгое время, но надеюсь, что это поможет кому-то, кто ищет простое решение и современные новички.
Теперь мы можем достичь этого, используя несколько библиотек, таких как lodash
, underscore
и т.д. (В настоящее время они становятся частью проекта из-за простоты, множества функций и большого использования)
Вы можете использовать пересечение из библиотеки lodash.
_.intersection(['2-1', '1'], ['2-2', '3-1', '2-1']);
// => ['2-1']
Это будет работать для любого типа данных..