Как узнать, имеют ли два массива одинаковые значения


у меня есть эти два массива: один заполнен информацией из запроса 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? Как я могу узнать, какие значения в первом массиве являются не во второй ли?

11 66

11 ответов:

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;

}

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

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

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

может быть?

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

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

короткие, простые и красивые!

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

в 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`

этот второй решение с помощью подчеркивание ближе к тому, что вы пытаетесь сделать:

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]`

обновление

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

обновление 2

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

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

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

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

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

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

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

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

if(array1.intersect(array2).length === array1.length) {
    alert("arrays are the same!");
}

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

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;

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

пожалуйста, проверьте этот ответ

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

С помощью ES6

мы будем использовать Ramda по equals функция, но вместо этого мы можем использовать Lodash или подчеркивание isEqual:

const R = require('ramda');

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

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