Как узнать, имеют ли два массива одинаковые значения - PullRequest
78 голосов
/ 03 июня 2011

У меня есть эти два массива: один заполнен информацией из запроса 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, даже если два массива одинаковы, но с разными именами. (Я проверил это в консоли JS Chrome). Итак, могу ли я узнать, содержат ли эти два массива одно и то же? Почему это дает false? Как узнать, какие значения в первом массиве отсутствуют во втором?

Ответы [ 13 ]

72 голосов
/ 03 июня 2011

Если ваши элементы массива не являются объектами, например, если они являются числами или строками, вы можете сравнить их объединенные строки, чтобы увидеть, имеют ли они одинаковые члены в любом порядке -

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');
42 голосов
/ 03 июня 2011
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();
}

Может быть?

40 голосов
/ 07 января 2015

Если вы хотите проверить только, имеют ли два массива одинаковые значения (независимо от количества экземпляров и порядка каждого значения), вы можете сделать это, используя lodash :

_.isEmpty(_.xor(array1, array2))

Коротко, просто и красиво!

23 голосов
/ 02 января 2016

Почему ваш код не работает

JavaScript имеет примитивные типы данных и не примитивные типы данных.

Для примитивных типов данных == и === проверяют, имеют ли значения по обе стороны от столбцов одинаковое значение. Вот почему 1 === 1 верно.

Для непримитивных типов данных, таких как массивы, == и === проверяют равенство ссылок. То есть они проверяют, являются ли arr1 и arr2 одним и тем же объектом. В вашем примере два массива имеют одинаковые объекты в одинаковом порядке, но не эквивалентны.

* Решения 1018 * Два массива, 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` Это второе решение с использованием Подчеркивание ближе к тому, что вы пытались сделать: 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: метод:

_.difference(arr1, arr2); // `[4]`

UPDATE

См. Комментарий @ Реду - мое решение для sameMembers, но вы можете иметь в виду sameMembersInOrder, также известный как deepEquals.

ОБНОВЛЕНИЕ 2

Если вас не волнует порядок членов массивов, ES2015 + Set может быть лучшей структурой данных, чем Array. См. MDN примечания о том, как реализовать isSuperset и difference, используя опасные исправления обезьян.

16 голосов
/ 18 апреля 2017
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;

}

Обратите внимание, что это не изменяет исходные массивы в отличие от предыдущего ответа.

6 голосов
/ 13 февраля 2014

Проверка на равенство объектов: JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())

Вышеупомянутый тест также работает с массивами объектов, в этом случае используется функция сортировки, как описано в http://www.w3schools.com/jsref/jsref_sort.asp

Может быть достаточно для небольших массивов с плоскими схемами JSON.

3 голосов
/ 03 июня 2011

Когда вы сравниваете эти два массива, вы сравниваете объекты, которые представляют массивы, а не их содержимое.

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

2 голосов
/ 10 апреля 2019

Наша цель в основном проверить, равны ли 2 массива.Здесь set означает математическое set .Самая быстрая сортировка асимптотически занимает 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 являются массивами

1 голос
/ 01 августа 2018

Использование ES6

Мы будем использовать функцию equals Рамды, но вместо этого мы можем использовать isEqual Lodash или Underscore *:

const R = require('ramda');

const arraysHaveSameValues = (arr1, arr2) => R.equals( [...arr1].sort(), [...arr2].sort() )

Используя противодействие распространению, мы избегаем мутацииоригинальные массивы, и мы сохраняем нашу функцию в чистоте.

1 голос
/ 08 июля 2015

У меня были простые целочисленные значения в игровом проекте
Если бы в каждом массиве также было меньше значений, исходный массив оставался нетронутым
Итак, я сделал ниже, все работало нормально. (Код отредактирован для вставки здесь)

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;

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...