Как сравнить массивы в JavaScript?

751

Я бы хотел сравнить два массива... идеально, эффективно. Ничего необычного, просто true, если они идентичны, и false, если нет. Неудивительно, что оператор сравнения не работает.

var a1 = [1,2,3];
var a2 = [1,2,3];
console.log(a1==a2);    // Returns false
console.log(JSON.stringify(a1)==JSON.stringify(a2));    // Returns true

JSON кодирует каждый массив, но существует ли более быстрый или "лучший" способ простого сравнения массивов без необходимости повторения каждого значения?

  • 5
    Вы могли бы сначала сравнить их длину, и если они равны каждому значению.
  • 42
    Что делает два массива равными для вас? Те же элементы? Одинаковый порядок элементов? Кодирование в формате JSON работает только до тех пор, пока элемент массива можно сериализовать в JSON. Если массив может содержать объекты, насколько глубоко вы пойдете? Когда два объекта "равны"?
Показать ещё 10 комментариев
Теги:
arrays

54 ответа

770
Лучший ответ

Чтобы сравнить массивы, прокрутите их и сравните каждое значение:

Сравнение массивов:

// Warn if overriding existing method
if(Array.prototype.equals)
    console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array prototype to call it on any array
Array.prototype.equals = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time 
    if (this.length != array.length)
        return false;

    for (var i = 0, l=this.length; i < l; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].equals(array[i]))
                return false;       
        }           
        else if (this[i] != array[i]) { 
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;   
        }           
    }       
    return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});

Применение:

[1, 2, [3, 4]].equals([1, 2, [3, 2]]) === false;
[1, "2,3"].equals([1, 2, 3]) === false;
[1, 2, [3, 4]].equals([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].equals([1, 2, 1, 2]) === true;

Вы можете сказать: "Но гораздо быстрее сравнивать строки - нет петель..." ну, тогда вы должны отметить, что ARE циклы. Первый рекурсивный цикл, который преобразует Array в строку и второй, который сравнивает две строки. Таким образом, этот метод быстрее, чем использование строки.

Я считаю, что большие объемы данных должны всегда храниться в массивах, а не в объектах.Однако, если вы используете объекты, их также можно частично сравнить.
Вот как:

Сравнение объектов:

Я уже говорил выше, что два экземпляра объекта никогда не будут равны, даже если они содержат одни и те же данные на данный момент:

({a:1, foo:"bar", numberOfTheBeast: 666}) == ({a:1, foo:"bar", numberOfTheBeast: 666})  //false

У этого есть причина, поскольку могут быть, например, частные переменные внутри объектов.

Однако, если вы просто используете структуру объектов для хранения данных, сравнение по-прежнему возможно:

Object.prototype.equals = function(object2) {
    //For the first loop, we only check for types
    for (propName in this) {
        //Check for inherited methods and properties - like .equals itself
        //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
        //Return false if the return value is different
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        //Check instance type
        else if (typeof this[propName] != typeof object2[propName]) {
            //Different types => not equal
            return false;
        }
    }
    //Now a deeper check using other objects property names
    for(propName in object2) {
        //We must check instances anyway, there may be a property that only exists in object2
            //I wonder, if remembering the checked values from the first loop would be faster or not 
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        else if (typeof this[propName] != typeof object2[propName]) {
            return false;
        }
        //If the property is inherited, do not check any more (it must be equa if both objects inherit it)
        if(!this.hasOwnProperty(propName))
          continue;

        //Now the detail check and recursion

        //This returns the script back to the array comparing
        /**REQUIRES Array.equals**/
        if (this[propName] instanceof Array && object2[propName] instanceof Array) {
                   // recurse into the nested arrays
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        else if (this[propName] instanceof Object && object2[propName] instanceof Object) {
                   // recurse into another objects
                   //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        //Normal value comparison for strings and numbers
        else if(this[propName] != object2[propName]) {
           return false;
        }
    }
    //If everything passed, let say YES
    return true;
}  

Однако помните, что это должно служить для сравнения JSON как данных, а не экземпляров классов и других вещей. Если вы хотите сравнить mor-сложные объекты, посмотрите на этот ответ и на эту функцию.
Чтобы сделать эту работу с Array.equals вы должны немного изменить исходную функцию:

...
    // Check if we have nested arrays
    if (this[i] instanceof Array && array[i] instanceof Array) {
        // recurse into the nested arrays
        if (!this[i].equals(array[i]))
            return false;
    }
    /**REQUIRES OBJECT COMPARE**/
    else if (this[i] instanceof Object && array[i] instanceof Object) {
        // recurse into another objects
        //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
        if (!this[i].equals(array[i]))
            return false;
        }
    else if (this[i] != array[i]) {
...

Я сделал небольшой тестовый инструмент для обеих функций.

Бонус: Вложенные массивы с indexOf и contains

Samy Bencherif подготовил полезные функции для случая, когда вы ищете определенный объект во вложенных массивах, которые доступны здесь: https://jsfiddle.net/SamyBencherif/8352y6yw/

  • 3
    Спасибо за ваш вклад. Учитывая его количество просмотров, я полагаю, что многие пользователи, перенаправленные сюда из Google, сталкиваются с одной и той же загадкой, чтобы выяснить, как именно "правильно" сравнить два массива!
  • 23
    Если вы хотите выполнять строгие сравнения, используйте this[i] !== array[i] вместо != .
Показать ещё 52 комментария
277

Хотя это работает только для скалярных массивов (см. Примечание ниже), это коротко:

array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})

Rr, в ECMAScript 6/CoffeeScript/TypeScript со стрелочными функциями:

array1.length === array2.length && array1.every((value, index) => value === array2[index])

(Примечание: здесь "скаляр" означает значения, которые можно сравнивать напрямую с помощью ===. Итак: числа, строки, объекты по ссылке, функции по ссылке. Подробнее о операторах сравнения см. Ссылку MDN).

ОБНОВИТЬ

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

array1.length === array2.length && array1.sort().every(function(value, index) { return value === array2.sort()[index]});

Например:

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

Тогда приведенный выше код дал бы true

  • 13
    Мне это нравится, хотя читатели должны знать, что это работает только на отсортированных массивах.
  • 9
    Работает на любых видах массивов, отсортированных или нет @espertus
Показать ещё 9 комментариев
169

Мне нравится использовать библиотеку Underscore для проектов тяжелого кодирования массива/объектов... в Underscore и Lodash, сравниваете ли вы массивы или объекты, это выглядит следующим образом:

_.isEqual(array1, array2)   // returns a boolean
_.isEqual(object1, object2) // returns a boolean
  • 18
    Обратите внимание, что порядок имеет значение _.isEqual([1,2,3], [2,1,3]) => false
  • 3
    или если вам нужна только функциональность isEqual , вы всегда можете использовать модуль lodash.isequal
Показать ещё 2 комментария
78

Это, я думаю, самый простой способ сделать это, используя JSON stringify, и это может быть лучшим решением в некоторых ситуациях:

JSON.stringify(a1) === JSON.stringify(a2);

Это преобразует объекты a1 и a2 в строки, чтобы их можно было сравнить. Порядок в большинстве случаев важен, поскольку он может сортировать объект с помощью алгоритма сортировки, показанного в одном из приведенных выше ответов.

Обратите внимание, что вы больше не сравниваете объект, а строковое представление объекта. Это может быть не совсем то, что вы хотите.

  • 0
    хороший ответ, но почему [] == [] вернуть false? оба простые объекты, то почему?
  • 3
    @PardeepJain, это потому, что по умолчанию оператор равенства в ECMAScript для объектов возвращает true, когда они ссылаются на одну и ту же ячейку памяти. Попробуйте var x = y = []; // теперь равенство возвращает true.
Показать ещё 6 комментариев
58

Неясно, что вы подразумеваете под "идентичными". Например, массивы a и b ниже идентичны (обратите внимание на вложенные массивы)?

var a = ["foo", ["bar"]], b = ["foo", ["bar"]];

Здесь оптимизированная функция сравнения массива, которая поочередно сравнивает соответствующие элементы каждого массива с использованием строгого равенства и не выполняет рекурсивного сравнения элементов массива, которые сами являются массивами, что означает, что в приведенном выше примере arraysIdentical(a, b) вернет false, Он работает в общем случае, решения на основе JSON- и join() не будут:

function arraysIdentical(a, b) {
    var i = a.length;
    if (i != b.length) return false;
    while (i--) {
        if (a[i] !== b[i]) return false;
    }
    return true;
};
  • 0
    @ASDF: из вопроса неясно, что означает «идентичный». Очевидно, этот ответ просто проверяет. Я добавлю заметку.
  • 0
    это не работает для массивов идентичных ([1, 2, [3, 2]], [1, 2, [3, 2]]);
Показать ещё 1 комментарий
49

Практический путь

Я думаю, что неправильно сказать, что конкретная реализация - это "Правильный путь", если она только "правильная" ("правильная"), в отличие от "неправильного" решения. Решение Tomáš - это четкое улучшение по сравнению с сопоставлением массивов на основе строк, но это не значит, что оно объективно "правильно". Что все равно? Это самый быстрый? Является ли это наиболее гибким? Легче ли это понять? Это быстрее отлаживается? Использует ли он наименьшие операции? Есть ли побочные эффекты? Ни одно решение не может иметь лучшее из всего.

Томаш мог сказать, что его решение идет быстро, но я бы также сказал, что это бесполезно сложно. Он пытается быть решением "все-в-одном", которое работает для всех массивов, вложенных или нет. Фактически, он даже принимает больше, чем просто массивы, как входные данные и все еще пытается дать "правильный" ответ.


Generics предлагают повторное использование

Мой ответ подойдет к проблеме по-разному. Я начну с общей процедуры arrayCompare, которая касается только arrayCompare через массивы. Оттуда мы построим другие основные функции сравнения, такие как arrayEqual и arrayDeepEqual и т.д.

// arrayCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayCompare = f => ([x,...xs]) => ([y,...ys]) =>
  x === undefined && y === undefined
    ? true
    : Boolean (f (x) (y)) && arrayCompare (f) (xs) (ys)

На мой взгляд, лучший вид кода даже не требует комментариев, и это не исключение. Здесь так мало происходит, что вы можете понять поведение этой процедуры почти без усилий. Конечно, некоторые из синтаксиса ES6 могут казаться вам чуждыми, но это только потому, что ES6 является относительно новым.

Как предполагает тип, arrayCompare принимает функцию сравнения, f и два входных массива xs и ys. По большей части все, что мы делаем, это вызов f (x) (y) для каждого элемента входных массивов. Мы возвращаем раннее значение false если пользовательский f возвращает false - благодаря && короткому замыканию. Таким образом, да, это означает, что компаратор может остановить итерацию раньше и предотвратить цикл через остальную часть входного массива, когда это не нужно.


Строгое сравнение

Затем, используя нашу функцию arrayCompare, мы можем легко создавать другие функции, которые могут потребоваться. Мы начнем с элементарного arrayEqual...

// equal :: a -> a -> Bool
const equal = x => y =>
  x === y // notice: triple equal

// arrayEqual :: [a] -> [a] -> Bool
const arrayEqual =
  arrayCompare (equal)

const xs = [1,2,3]
const ys = [1,2,3]
console.log (arrayEqual (xs) (ys))      //=> true
// (1 === 1) && (2 === 2) && (3 === 3)  //=> true

const zs = ['1','2','3']
console.log (arrayEqual (xs) (zs))      //=> false
// (1 === '1')                          //=> false

Просто как тот. arrayEqual может быть определен с помощью arrayCompare и функцией сравнения, которая сравнивает a и b используя === (для строгого равенства).

Обратите внимание, что мы также определяем equal собственную функцию. Это подчеркивает роль arrayCompare как функции более высокого порядка для использования нашего первого компаратора порядка в контексте другого типа данных (Array).


Свободное сравнение

Мы могли бы так же легко определить arrayLooseEqual используя вместо этого ==. Теперь, сравнивая 1 (Number) с '1' (String), результат будет true...

// looseEqual :: a -> a -> Bool
const looseEqual = x => y =>
  x == y // notice: double equal

// arrayLooseEqual :: [a] -> [a] -> Bool
const arrayLooseEqual =
  arrayCompare (looseEqual)

const xs = [1,2,3]
const ys = ['1','2','3']
console.log (arrayLooseEqual (xs) (ys))    //=> true
// (1 == '1') && (2 == '2') && (3 == '3')  //=> true

Глубокое сравнение (рекурсивное)

Вы, наверное, заметили, что это только мелкое сравнение. Разумеется, решение Томаша - "Правильный путь", потому что оно подразумевает глубокое сравнение, верно?

Ну, наша процедура arrayCompare достаточно универсальна, чтобы использовать ее таким образом, чтобы сделать глубокий тест на равномерность...

// isArray :: a -> Bool
const isArray =
  Array.isArray

// arrayDeepCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayDeepCompare = f =>
  arrayCompare (a => b =>
    isArray (a) && isArray (b)
      ? arrayDeepCompare (f) (a) (b)
      : f (a) (b))

const xs = [1,[2,[3]]]
const ys = [1,[2,['3']]]
console.log (arrayDeepCompare (equal) (xs) (ys)) //=> false
// (1 === 1) && (2 === 2) && (3 === '3')         //=> false

console.log (arrayDeepCompare (looseEqual) (xs) (ys)) //=> true
// (1 == 1) && (2 == 2) && (3 == '3')                 //=> true

Просто как тот. Мы строим глубокий компаратор, используя другую функцию более высокого порядка. На этот раз мы arrayCompare с помощью специализированного компаратора, который будет проверять, являются ли массивы a и b массивами. Если это так, повторно примените arrayDeepCompare противном случае сравните a и b с указанным пользователем компаратором (f). Это позволяет нам сохранять глубокое сравнительное поведение отдельно от того, как мы фактически сравниваем отдельные элементы. Т.е., как показано в приведенном выше примере, мы можем looseEqual глубокое сравнение с использованием equal, looseEqual или любого другого компаратора, который мы делаем.

Поскольку arrayDeepCompare находится в arrayDeepCompare, мы можем частично применить его так же, как и в предыдущих примерах

// arrayDeepEqual :: [a] -> [a] -> Bool
const arrayDeepEqual =
  arrayDeepCompare (equal)

// arrayDeepLooseEqual :: [a] -> [a] -> Bool
const arrayDeepLooseEqual =
  arrayDeepCompare (looseEqual)

Для меня это уже явное улучшение по сравнению с решением Томаша, потому что я могу явно выбрать мелкое или глубокое сравнение для своих массивов по мере необходимости.


Сравнение объектов (пример)

Теперь, если у вас есть массив объектов или что-то еще? Возможно, вы хотите считать эти массивы "равными", если каждый объект имеет одинаковое значение id...

// idEqual :: {id: Number} -> {id: Number} -> Bool
const idEqual = x => y =>
  x.id !== undefined && x.id === y.id

// arrayIdEqual :: [a] -> [a] -> Bool
const arrayIdEqual =
  arrayCompare (idEqual)

const xs = [{id:1}, {id:2}]
const ys = [{id:1}, {id:2}]
console.log (arrayIdEqual (xs) (ys)) //=> true
// (1 === 1) && (2 === 2)            //=> true

const zs = [{id:1}, {id:6}]
console.log (arrayIdEqual (xs) (zs)) //=> false
// (1 === 1) && (2 === 6)            //=> false

Просто как тот. Здесь я использовал объекты Vanilla JS, но этот тип компаратора мог работать для любого типа объекта; даже ваши пользовательские объекты. Решение Tomáš должно быть полностью переработано для поддержки такого теста равенства

Глубокий массив с объектами? Не проблема. Мы создали универсальные универсальные функции, поэтому они будут работать в самых разных вариантах использования.

const xs = [{id:1}, [{id:2}]]
const ys = [{id:1}, [{id:2}]]
console.log (arrayCompare (idEqual) (xs) (ys))     //=> false
console.log (arrayDeepCompare (idEqual) (xs) (ys)) //=> true

Произвольное сравнение (пример)

Или что, если вы хотите сделать какой-то другой вид совершенно произвольного сравнения? Может быть, я хочу знать, если каждый x больше, чем каждый из y...

// gt :: Number -> Number -> Bool
const gt = x => y =>
  x > y

// arrayGt :: [a] -> [a] -> Bool
const arrayGt = arrayCompare (gt)

const xs = [5,10,20]
const ys = [2,4,8]
console.log (arrayGt (xs) (ys))     //=> true
// (5 > 2) && (10 > 4) && (20 > 8)  //=> true

const zs = [6,12,24]
console.log (arrayGt (xs) (zs))     //=> false
// (5 > 6)                          //=> false

Меньше - больше

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

С легкостью мы можем точно определить, как мы хотим сравнить два массива: мелкое, глубокое, строгое, свободное, какое-либо свойство объекта или какое-то произвольное вычисление или любую их комбинацию - все, используя одну процедуру, arrayCompare. Может быть, даже придумать RegExp ! Я знаю, как дети любят эти регулярные выражения...

Это самый быстрый? Неа. Но, вероятно, это тоже не обязательно. Если скорость - это единственная метрика, используемая для измерения качества нашего кода, то очень хороший код будет выброшен - вот почему я называю этот подход "Практический путь". Или, может быть, быть более справедливым, Практический путь. Это описание подходит для этого ответа, потому что я не говорю, что этот ответ практичен только по сравнению с другим ответом; это объективно верно. Мы достигли высокой степени практичности с очень маленьким кодом, который очень легко рассуждать. Никакой другой код не может сказать, что мы не заработали это описание.

Это делает это "правильным" решением для вас? Это вам решать. И никто другой не может этого сделать для вас; только вы знаете, что ваши потребности. Почти во всех случаях я ценю простой, практичный и универсальный код с умным и быстрым видом. То, что вы цените, может отличаться, поэтому выберите то, что работает для вас.


редактировать

Мой старый ответ был более сфокусирован на разложении arrayEqual на крошечные процедуры. Это интересное упражнение, но не самый лучший (наиболее практичный) способ решения этой проблемы. Если вам интересно, вы можете увидеть эту историю изменений.

  • 0
    +1 за «лучший вид кода даже не нуждается в комментариях» и ваш прекрасный ответ, конечно. Тем не менее, мне интересно, почему вы решили против Array.prorotype.every . Требуется предикат и итерация может быть остановлена рано. Его также легко прочитать, если вы знаете, что переданная функция имеет необязательный второй аргумент: f => xs => ys => xs.length === ys.length ? xs.every((y, x) => f(x) (ys[y])) : false . Я думаю, что реализация более эффективна для памяти. Это спорно , если это идиоматическое использование every хотя. ys[y] раскрывает алгоритмические детали и менее декларативен ...
  • 0
    @ LUH3417 Да, я мог бы использовать. .every как вы описали, вы можете переключать параметры x и y - xs.every((x,i) => f (x) (ys[i])) . Я думаю, что это полезное и идиоматическое приложение .every но я действительно хотел показать, как создать общую процедуру высшего порядка с нуля. Кроме того, я знаю, что .length и доступ к элементу массива по индексу ( ys[i] ) не очень дороги в JavaScript, но я хотел показать, что это можно сделать и без них.
Показать ещё 23 комментария
32

В духе оригинального вопроса:

Я бы хотел сравнить два массива... идеально, эффективно. нет Ничего fancy, просто true, если они идентичны, а false, если нет.

Я выполнял тесты производительности на некоторые из более простых предложений, предложенных здесь, со следующими результатами (быстрый и медленный):

пока (67%) by Tim Down

var i = a1.length;
while (i--) {
    if (a1[i] !== a2[i]) return false;
}
return true

каждый (69%) от пользователя2782196

a1.every((v,i)=> v === a2[i]);

уменьшить (74%) по DEI

a1.reduce((a, b) => a && a2.includes(b), true);

присоединиться и toString (78%) от Gaizka Allende и vivek

a1.join('') === a2.join('');

a1.toString() === a2.toString();

половина toString (90%) от Виктора Паломо

a1 == a2.toString();

stringify (100%) от radtek

JSON.stringify(a1) === JSON.stringify(a2);

Примечание приведенные ниже примеры предполагают, что массивы отсортированы, одномерные массивы. .length сравнение было удалено для общего теста (добавьте a1.length === a2.length к любому из предложений, и вы получите повышение производительности на 10%). Выберите любые решения, которые лучше всего подходят для вас, зная скорость и ограничение каждого из них.

Несвязанное примечание: интересно видеть, как люди получают все триггер-счастливые Джон Уэйнс на кнопке с правом голоса на совершенно законных ответах на этот вопрос.

  • 0
    По ссылке открывается пустой тест.
27

Создав ответ Томаша Зато, я согласен с тем, что простое повторение массивов является самым быстрым. Кроме того (как уже отмечали другие), функцию следует называть равной/равной, а не сравнивать. В свете этого я модифицировал функцию, чтобы обрабатывать массивы для сходства - т.е. Они имеют одни и те же элементы, но не в порядке - для личного использования, и я думал, что брошу их здесь для всеобщего обозрения.

Array.prototype.equals = function (array, strict) {
    if (!array)
        return false;

    if (arguments.length == 1)
        strict = true;

    if (this.length != array.length)
        return false;

    for (var i = 0; i < this.length; i++) {
        if (this[i] instanceof Array && array[i] instanceof Array) {
            if (!this[i].equals(array[i], strict))
                return false;
        }
        else if (strict && this[i] != array[i]) {
            return false;
        }
        else if (!strict) {
            return this.sort().equals(array.sort(), true);
        }
    }
    return true;
}

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

Пример:

var arr1 = [1, 2, 3, 4];
var arr2 = [2, 1, 4, 3];  // Loosely equal to 1
var arr3 = [2, 2, 3, 4];  // Not equal to 1
var arr4 = [1, 2, 3, 4];  // Strictly equal to 1

arr1.equals(arr2);         // false
arr1.equals(arr2, false);  // true
arr1.equals(arr3);         // false
arr1.equals(arr3, false);  // false
arr1.equals(arr4);         // true
arr1.equals(arr4, false);  // true

Я также написал быстрый jsfiddle с функцией и этим примером:
http://jsfiddle.net/Roundaround/DLkxX/

8

Несмотря на то, что у этого есть много ответов, я полагаю, что это поможет:

const newArray = [ ...new Set( [...arr1, ...arr2] ) ]

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

В результате мы используем оператор распространения (...) для объединения обоих массивов, а затем используем Set для устранения любых дубликатов. Если у вас есть это, вы можете сравнить их размеры, если все три массива имеют одинаковый размер, вы можете пойти.

Этот ответ также игнорирует порядок элементов, как я уже говорил, точная ситуация произошла со мной, поэтому, возможно, кто-то в такой же ситуации может оказаться здесь (как я).


Edit1.

Отвечая на вопрос Дмитрия Гринько: "Почему вы использовали оператор распространения (...) здесь -... новый сет? Он не работает"

Рассмотрим этот код:

const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ new Set( [...arr1, ...arr2] ) ]
console.log(newArray)

Ты получишь

[ Set { 'a', 'b', 'c' } ]

Чтобы работать с этим значением, вам нужно использовать некоторые свойства Set (см. Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set). С другой стороны, когда вы используете этот код:

const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ ...new Set( [...arr1, ...arr2] ) ]
console.log(newArray)

Ты получишь

[ 'a', 'b', 'c' ]

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

  • 0
    Почему вы использовали оператор распространения (...) здесь - ... новый сет? Не работает
  • 0
    Дмитрий Гринько Я думаю, что я ответил на ваш вопрос на моем Edit1. Но я не уверен, что вы имели в виду, говоря «это не работает», так как оба ответа могут вам помешать
7

В тех же строках, что и JSON.encode, следует использовать join().

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;


    //slice so we do not effect the original
    //sort makes sure they are in order
    //join makes it a string so we can do a string compare
    var cA = arrA.slice().sort().join(","); 
    var cB = arrB.slice().sort().join(",");

    return cA===cB;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];  //will return true

console.log( checkArrays(a,b) );  //true
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //true

Только проблема заключается в том, что вам нужны типы, которые были последними сравнительными тестами. Если вам нравятся типы, вам придется зацикливаться.

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;

    //slice so we do not effect the orginal
    //sort makes sure they are in order
    var cA = arrA.slice().sort(); 
    var cB = arrB.slice().sort();

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

    return true;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];

console.log( checkArrays(a,b) );  //true
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //false

Если порядок должен оставаться таким же, как это просто цикл, никакой сортировки не требуется.

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;


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

    return true;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];

console.log( checkArrays(a,a) );  //true
console.log( checkArrays(a,b) );  //false
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //false
  • 0
    Спасибо, @epascarello, в моем конкретном случае я сравниваю только порядок элементов, а не типов, поэтому .join(); будет работать так же. Спасибо за понимание.
  • 0
    С вашей первой версией checkArrays() : checkArrays([11,22,33,44], [1,12,23,344]) // true
Показать ещё 12 комментариев
6

Если это только два массива чисел или строк, это быстрый однострочный

const array1 = [1, 2, 3];
const array2 = [1, 3, 4];
console.log(array1.join(',') === array2.join(',')) //false

const array3 = [1, 2, 3];
const array4 = [1, 2, 3];
console.log(array3.join(',') === array4.join(',')) //true
  • 0
    const array1 = [1]; const array2 = [1, 1]; console.log (array1.join ('') === array2.join ('')) // возвращает true
  • 0
    это не должно быть: array1.join ('') равно '1', а array2.join ('') равно '11'
Показать ещё 7 комментариев
5

Если вы используете платформу тестирования, например Mocha, Chai, вы можете использовать deep равенство для сравнения массивов.

expect(a1).to.deep.equal(a2)

Это должно возвращать true, только если массивы имеют равные элементы в соответствующих индексах.

5

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

arr1.sort().toString() == arr2.sort().toString()

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

  • 0
    Вы можете использовать строгую проверку на равенство === (чтобы осчастливить линтера), если рассматриваемые массивы действительно содержат строковые элементы.
  • 3
    Сбой для [1,2] и ["1,2"] . Обратите внимание, что вызов the sort() изменит входные массивы - это может быть нежелательно.
3

Вот версия машинописного текста:

//https://stackoverflow.com/a/16436975/2589276
export function arraysEqual<T>(a: Array<T>, b: Array<T>): boolean {
    if (a === b) return true
    if (a == null || b == null) return false
    if (a.length != b.length) return false

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

//https://stackoverflow.com/a/16436975/2589276
export function arraysDeepEqual<T>(a: Array<T>, b: Array<T>): boolean {
    return JSON.stringify(a) === JSON.stringify(b)
}

Некоторые тестовые примеры для мокко:

it('arraysEqual', function () {
    let a = [1,2]
    let b = [1,2]
    let c = [2,3]
    let d = [2, 3]
    let e = ['car','apple','banana']
    let f = ['car','apple','banana']
    let g = ['car','apple','banan8']

    expect(arraysEqual(a, b)).to.equal(true)
    expect(arraysEqual(c, d)).to.equal(true)
    expect(arraysEqual(a, d)).to.equal(false)
    expect(arraysEqual(e, f)).to.equal(true)
    expect(arraysEqual(f, g)).to.equal(false)
})

it('arraysDeepEqual', function () {
    let a = [1,2]
    let b = [1,2]
    let c = [2,3]
    let d = [2, 3]
    let e = ['car','apple','banana']
    let f = ['car','apple','banana']
    let g = ['car','apple','banan8']
    let h = [[1,2],'apple','banan8']
    let i = [[1,2],'apple','banan8']
    let j = [[1,3],'apple','banan8']

    expect(arraysDeepEqual(a, b)).to.equal(true)
    expect(arraysDeepEqual(c, d)).to.equal(true)
    expect(arraysDeepEqual(a, d)).to.equal(false)
    expect(arraysDeepEqual(e, f)).to.equal(true)
    expect(arraysDeepEqual(f, g)).to.equal(false)
    expect(arraysDeepEqual(h, i)).to.equal(true)
    expect(arraysDeepEqual(h, j)).to.equal(false)
})
3

Это сравнивает 2 несортированных массива:

function areEqual(a, b) {
  if ( a.length != b.length) {
    return false;
  }
  return a.filter(function(i) {
    return !b.includes(i);
  }).length === 0;  
}
3

Мы могли бы сделать это функциональным способом, используя every (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every)

function compareArrays(array1, array2) {
    if (array1.length === array2.length)
        return array1.every((a, index) => a === array2[index])
    else
        return false
}

// test
var a1 = [1,2,3];
var a2 = [1,2,3];

var a3 = ['a', 'r', 'r', 'a', 'y', '1']
var a4 = ['a', 'r', 'r', 'a', 'y', '2']

console.log(compareArrays(a1,a2)) // true
console.log(compareArrays(a1,a3)) // false
console.log(compareArrays(a3,a4)) // false
3

Вот мое решение:

/**
 * Tests two data structures for equality
 * @param {object} x
 * @param {object} y
 * @returns {boolean}
 */
var equal = function(x, y) {
    if (typeof x !== typeof y) return false;
    if (x instanceof Array && y instanceof Array && x.length !== y.length) return false;
    if (typeof x === 'object') {
        for (var p in x) if (x.hasOwnProperty(p)) {
            if (typeof x[p] === 'function' && typeof y[p] === 'function') continue;
            if (x[p] instanceof Array && y[p] instanceof Array && x[p].length !== y[p].length) return false;
            if (typeof x[p] !== typeof y[p]) return false;
            if (typeof x[p] === 'object' && typeof y[p] === 'object') { if (!equal(x[p], y[p])) return false; } else
            if (x[p] !== y[p]) return false;
        }
    } else return x === y;
    return true;
};

Работает с любой вложенной структурой данных и, очевидно, игнорирует методы объектов. Даже не думайте о расширении Object.prototype с помощью этого метода, когда я попробовал это однажды, jQuery сломался;)

Для большинства массивов он все же быстрее, чем большинство решений для сериализации. Вероятно, это самый быстрый метод сравнения для массивов записей объектов.

  • 0
    не хорошо! они дают истину: equal({}, {a:1}) и equal({}, null) и это equal({a:2}, null) ошибкам: equal({a:2}, null)
2

Пока == сравнивает указатели на массив, часто забывают, что < и > работают довольно хорошо. Итак, одно простое решение:

  function eq(a,b){return !(a<b || b<a);}

Кажется, что он работает неплохо, но, похоже, немного теряет контроль над типом:

eq([1,2],[])
false
eq([1,2],[1,2,0])
false
eq([1,2,0],[1,2,0])
true
eq([1,2,0],[1,2,null])
false
eq([1,2,0],[1,2,"0"])
true
eq([1,2,0],[1,2,[0]])
true
eq([1,2,[0],[3]],[1,2,[0,3]])
true
eq([1,2,[0],[3]],[1,2,[0,4]])
false
eq([1,2,[0],[3]],[1,2,"0,3"])
true

Итак, до тех пор, пока ваши массивы содержат только числа, он должен работать нормально, и, безусловно, хороший короткий хак:)

2
var a1 = [1,2,3,6];
var a2 = [1,2,3,5];

function check(a, b) {
  return (a.length != b.length) ? false : 
  a.every(function(row, index) {
    return a[index] == b[index];
  });
}  

check(a1, a2);

//////ИЛИ///////

var a1 = [1,2,3,6];
var a2 = [1,2,3,6];

function check(a, b) {
  return (a.length != b.length) ? false : 
  !(a.some(function(row, index) {
    return a[index] != b[index];
  }));
}  

check(a1, a2)
  • 0
    Вы можете также использовать некоторую функцию, которая не будет повторяться полностью, если мы выполним требуемое условие, как указано выше.
1

Сравнение 2 массивов:

var arr1 = [1,2,3];
var arr2 = [1,2,3];

function compare(arr1,arr2)
{
  if((arr1 == arr2) && (arr1.length == arr2.length))
    return true;
  else
    return false;
}

вызывающая функция

var isBool = compare(arr1.sort().join(),arr2.sort().join());
  • 0
    Этот ответ не будет работать, так как === не работает так, как ожидается для массивов.
  • 0
    Ответ работает, хотя === здесь не имеет никакого значения (поскольку sort () работает только с массивом). Даже == тоже будет работать.
Показать ещё 3 комментария
1
JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ?  array.push(collection[i]) : null

Вот как я это сделал.

  • 0
    Хорошее решение - но мне интересно в некоторых ситуациях, если оно не всегда будет работать так, как задумано, например, с определенными примитивами или глубоко вложенными массивами? Я надеюсь, что это работает при любых обстоятельствах, хотя
  • 0
    Я не уверен, работает ли он во вложенных массивах.
1

Выберите каждый из [a] и пропустите все из [b]: Результат: 1, 5

var a = [1,4,5,9];
var b = [1,6,7,5];

for (i = 0; i < a.length; i++) {
    for (z = 0; z < a.length; z++) {
        if (a[i] === b[z]) {
            console.log(b[z]); // if match > console.log it 
        }
    }
}
1

Другой подход с очень небольшим количеством кода (с помощью Array уменьшить и Массив включает в себя):

arr1.length == arr2.length && arr1.reduce((a, b) => a && arr2.includes(b), true)

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

arr1.length == arr2.length && arr1.reduce((a, b, i) => a && arr2[i], true)
  • Проверка length гарантирует, что набор элементов в одном массиве не является только подмножеством другого.

  • Редуктор используется для перехода через один массив и поиска каждого элемента в другом массиве. Если один элемент не найден, функция уменьшения возвращает false.

    • В первом примере тестируется, что элемент включен
    • Второй пример также проверяет порядок.
  • 1
    Не могли бы вы немного объяснить свой код, чтобы сделать этот ответ более понятным?
  • 0
    1. сравните длины массивов, чтобы убедиться, что один массив не является подмножеством другого
Показать ещё 2 комментария
1

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

взгляните на эту ссылку, она вас не вызывает сомнений простой способ понять, как работает оператор идентификации

1

Эта функция сравнивает два массива произвольной формы и dimesionality:

function equals(a1, a2) {

    if (!Array.isArray(a1) || !Array.isArray(a2)) {
        throw new Error("Arguments to function equals(a1, a2) must be arrays.");
    }

    if (a1.length !== a2.length) {
        return false;
    }

    for (var i=0; i<a1.length; i++) {
        if (Array.isArray(a1[i]) && Array.isArray(a2[i])) {
            if (equals(a1[i], a2[i])) {
                continue;
            } else {
                return false;
            }
        } else {
            if (a1[i] !== a2[i]) {
                return false;
            }
        }
    }

    return true;
}
1

этот script сравнивает объекты, массивы и многомерный массив

function compare(a,b){
     var primitive=['string','number','boolean'];
     if(primitive.indexOf(typeof a)!==-1 && primitive.indexOf(typeof a)===primitive.indexOf(typeof b))return a===b;
     if(typeof a!==typeof b || a.length!==b.length)return false;
     for(i in a){
          if(!compare(a[i],b[i]))return false;
     }
     return true;
}

первая строка проверяет, является ли это примитивным типом. если это так, он сравнивает два параметра.

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

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

var a=[1,2,[1,2]];
var b=[1,2,[1,2]];
var isEqual=compare(a,b);  //true
1

Расширение идеи Томаша Зато. Tomas Array.prototype.compare должен быть infact, называемый Array.prototype.compareIdentical.

Он проходит:

[1, 2, [3, 4]].compareIdentical ([1, 2, [3, 2]]) === false;
[1, "2,3"].compareIdentical ([1, 2, 3]) === false;
[1, 2, [3, 4]].compareIdentical ([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].compareIdentical ([1, 2, 1, 2]) === true;

Но не выполняется:

[[1, 2, [3, 2]],1, 2, [3, 2]].compareIdentical([1, 2, [3, 2],[1, 2, [3, 2]]])

Здесь лучше (на мой взгляд) версия:

Array.prototype.compare = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time
    if (this.length != array.length)
        return false;

    this.sort();
    array.sort();
    for (var i = 0; i < this.length; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].compare(array[i]))
                return false;
        }
        else if (this[i] != array[i]) {
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;
        }
    }
    return true;
}

http://jsfiddle.net/igos/bcfCY/

  • 2
    -1. Если в примере, который вы привели, он «проваливается», то это только в случае произвольного определения «провалов». Почему вы ожидаете, что эти два разных массива будут считаться равными? Вы даже не объяснили, какую концепцию «равенства» вы пытаетесь реализовать здесь, или почему она разумна или полезна, но похоже, что вы хотите, чтобы многомерные массивы сравнивались так, как если бы они были свернуты в одномерные из них. Если это так, вы даже не достигли этого: [1,2] .compare ([[1,2]]) выдает false с вашей версией, как и с Томашем.
  • 0
    Исходя из того, что я могу сделать вывод, он говорит, что [1, 2, 3, 4] и [1, 3, 2, 4] следует сравнивать как равные (порядок не имеет значения).
1

В моем случае сравниваемые массивы содержат только числа и строки. Эта функция покажет вам, содержат ли массивы одинаковые элементы.

function are_arrs_match(arr1, arr2){
    return arr1.sort().toString() === arr2.sort().toString()
}

Протестируйте его!

arr1 = [1, 2, 3, 'nik']
arr2 = ['nik', 3, 1, 2]
arr3 = [1, 2, 5]

console.log (are_arrs_match(arr1, arr2)) //true
console.log (are_arrs_match(arr1, arr3)) //false
  • 0
    Вопрос не требует от вас сортировки, поэтому ваше решение неверно для таких примеров, как are_arrs_equal([1,2], [2,1]) . Кроме того, посмотрите другие обсуждения на этой странице, чтобы узнать, почему строковые функции не нужны, хрупки и неправильны.
  • 0
    are_arrs_equal([1,2], [2,1]) возвращает true как и ожидалось. Возможно, это решение не идеальное, но оно сработало для меня.
Показать ещё 4 комментария
0

Вот очень короткий способ сделать это

function arrEquals(arr1, arr2){
     arr1.length == arr2.length && 
     arr1.filter(elt=>arr2.includes(elt)).length == arr1.length
}
0
function arraysMatch(arr1, arr2){
    if(arr1.length != arr2.length){
        return false
    }
    for(var i = 0; i < arr1.length; i++){
        if(arr1[i] != arr2[i]){
            return false;
        }
    }
    return true;
}
0

Рекурсивный и работает над массивами NESTED:

function ArrEQ(a1,a2){
   return( 
        //:Are both elements arrays?
        Array.isArray(a1)&&Array.isArray(a2) 
        ?
        //:Yes: Test each entry for equality:
        a1.every((v,i)=>(ArrEQ(v,a2[i])))
        :
        //:No: Simple Comparison:
        (a1===a2)
   );;
};;

console.log( "Works With Nested Arrays:" );
console.log( ArrEQ( 
    [1,2,3,[4,5,[6,"SAME/IDENTICAL"]]],
    [1,2,3,[4,5,[6,"SAME/IDENTICAL"]]]
));;     
console.log( ArrEQ( 
    [1,2,3,[4,5,[6,"DIFFERENT:APPLES" ]]],
    [1,2,3,[4,5,[6,"DIFFERENT:ORANGES"]]]
));;  
0

Работает с MULTIPLE аргументами с массивами NESTED:

//:Return true if all of the arrays equal.
//:Works with nested arrays.
function AllArrEQ(...arrays){
    for(var i = 0; i < (arrays.length-1); i++ ){
        var a1 = arrays[i+0];
        var a2 = arrays[i+1];
        var res =( 
            //:Are both elements arrays?
            Array.isArray(a1)&&Array.isArray(a2) 
            ?
            //:Yes: Compare Each Sub-Array:
            //:v==a1[i]
            a1.every((v,i)=>(AllArrEQ(v,a2[i])))
            :
            //:No: Simple Comparison:
            (a1===a2)
        );;
        if(!res){return false;}
    };;
    return( true );
};;

console.log( AllArrEQ( 
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
));; 
0

С возможностью сравнения заказа или нет:

function arraysEqual(a1, a2, compareOrder) {
    if (a1.length !== a2.length) {
        return false;
    }

    return a1.every(function(value, index) {
        if (compareOrder) {
            return value === a2[index];
        } else {
            return a2.indexOf(value) > -1;
        }
    });
}
0

Простой подход:

function equals(a, b) {
    if ((a && !b) || (!a && b) || (!a && !b) || (a.length !== b.length)) {
        return false;
    }

    var isDifferent = a.some(function (element, index) { 
        return element !== b[index];
    });

    return !isDifferent;
}
0

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

var a1 = [1,2,3];
var a2 = [1,2,3];
if (a1.length !== a2.length) {
   console.log('a1 and a2 are not equal')
}else if(a1.join(':') === a2.join(':')){
   console.log('a1 and a2 are equal')
}else{
   console.log('a1 and a2 are not equal')
}
0

попробовал deep-equal, и он работал

var eq = require('deep-equal');
eq({a: 1, b: 2, c: [3, 4]}, {c: [3, 4], a: 1, b: 2});
0

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

Ниже приведен мой собственный код для сравнения массивов и объектов. Код короткий и простой:

Array.prototype.equals = function(otherArray) {
  if (!otherArray || this.length != otherArray.length) return false;
  return this.reduce(function(equal, item, index) {
    var otherItem = otherArray[index];
    var itemType = typeof item, otherItemType = typeof otherItem;
    if (itemType !== otherItemType) return false;
    return equal && (itemType === "object" ? item.equals(otherItem) : item === otherItem);
  }, true);
};

if(!Object.prototype.keys) {
  Object.prototype.keys = function() {
    var a = [];
    for (var key in this) {
      if (this.hasOwnProperty(key)) a.push(key);
    }
    return a;
  }
  Object.defineProperty(Object.prototype, "keys", {enumerable: false});
}

Object.prototype.equals = function(otherObject) {
  if (!otherObject) return false;
  var object = this, objectKeys = object.keys();
  if (!objectKeys.equals(otherObject.keys())) return false;
  return objectKeys.reduce(function(equal, key) {
    var value = object[key], otherValue = otherObject[key];
    var valueType = typeof value, otherValueType = typeof otherValue;
    if (valueType !== otherValueType) return false;
    // this will call Array.prototype.equals for arrays and Object.prototype.equals for objects
    return equal && (valueType === "object" ? value.equals(otherValue) : value === otherValue);
  }, true);
}
Object.defineProperty(Object.prototype, "equals", {enumerable: false});

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

Вы можете увидеть полный набор тестов и проверить код самостоятельно в этом реплике: https://repl.it/Esfz/3

0

Если массив является простым и порядок имеет значение, поэтому две строки могут помочь

//Assume
var a = ['a','b', 'c']; var b = ['a','e', 'c'];  

if(a.length !== b.length) return false;
return !a.reduce(
  function(prev,next,idx, arr){ return prev || next != b[idx] },false
); 

Уменьшает количество проходов по одному из массивов и возвращает "false", если хотя бы один элемент "a" не равен элементу "b", Просто оберните это в функцию

  • 0
    Карта, уменьшить, отфильтровать все! :П
  • 0
    Это плохое решение , потому что Array.prototype.reduce будет пройти через каждый элемент в даже если первые по сравнению элементы не совпадают. a Также использование !a и != В цикле является двойным отрицанием, что делает этот ответ более сложным (и трудным для чтения), чем это должно быть
Показать ещё 1 комментарий
0

Здесь версия CoffeeScript для тех, кто предпочитает это:

Array.prototype.equals = (array) ->
  return false if not array # if the other array is a falsy value, return
  return false if @length isnt array.length # compare lengths - can save a lot of time

  for item, index in @
    if item instanceof Array and array[index] instanceof Array # Check if we have nested arrays
      if not item.equals(array[index]) # recurse into the nested arrays
        return false
    else if this[index] != array[index]
      return false # Warning - two different object instances will never be equal: {x:20} != {x:20}
  true

Все кредиты принадлежат @tomas-zato.

  • 0
    Array::equals
0
function compareArrays(arrayA, arrayB) {
    if (arrayA.length != arrayB.length) return true;
    for (i = 0; i < arrayA.length; i++)
        if (arrayB.indexOf(arrayA[i]) == -1) {
            return true;
        }
    }
    for (i = 0; i < arrayB.length; i++) {
        if (arrayA.indexOf(arrayB[i]) == -1) {
            return true;
        }
    }
    return false;
}
0

В моем решении сравниваются объекты, а не массивы. Это будет работать так же, как Tomáš as Arrays - это объекты, но без предупреждения:

Object.prototype.compare_to = function(comparable){

    // Is the value being compared an object
    if(comparable instanceof Object){

        // Count the amount of properties in @comparable
        var count_of_comparable = 0;
        for(p in comparable) count_of_comparable++;

        // Loop through all the properties in @this
        for(property in this){

            // Decrements once for every property in @this
            count_of_comparable--;

            // Prevents an infinite loop
            if(property != "compare_to"){

                // Is the property in @comparable
                if(property in comparable){

                    // Is the property also an Object
                    if(this[property] instanceof Object){

                        // Compare the properties if yes
                        if(!(this[property].compare_to(comparable[property]))){

                            // Return false if the Object properties don't match
                            return false;
                        }
                    // Are the values unequal
                    } else if(this[property] !== comparable[property]){

                        // Return false if they are unequal
                        return false;
                    }
                } else {

                    // Return false if the property is not in the object being compared
                    return false;
                }
            }
        }
    } else {

        // Return false if the value is anything other than an object
        return false;
    }

    // Return true if their are as many properties in the comparable object as @this
    return count_of_comparable == 0;
}

Надеюсь, это поможет вам или кому-либо еще найти ответ.

-1

Вы можете сравнить два массива, присоединив их, используя join('').
Это работает как для массивов чисел, так и для массивов строк.

Например:
[1, 2].join('') === [1, 2].join('') возвращает true
['a', 'b'].join('') === ['a', 'b'].join('') return true

-1

Мне очень нравится этот подход, поскольку он значительно более краткий, чем другие. Он по существу контрастирует все элементы с аккумулятором, который поддерживает то же значение, которое заменяется NaN если оно достигает единицы, которая отличается. Поскольку NaN не может быть равно любому значению, включая NaN, значение будет преобразовано в логическое (!!) и будет ложным. В противном случае значение должно быть истинным. Чтобы исключить массив нулей для возврата false, выражение преобразуется в его абсолютное значение и добавляется к 1, таким образом !!(Math.abs(0) + 1) будет true. Абсолютное значение было добавлено для случая -1, которое, когда добавлено к 1, будет равно 0 и, значит, false.

function areArrayItemsEqual(arr) {
    return !!(Math.abs(arr.reduce((a, b) => a === b ? b : NaN)) + 1);
}
-1

Уже есть несколько отличных ответов. Но я хотел бы поделиться идеей о другом, которая оказалась надежной при сравнении массивов. Мы можем сравнить два массива с помощью JSON.stringify(). Он будет создавать строку из массива и, таким образом, сравнить две полученные строки из двух массивов для равенства

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:1},2]) //true

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},2]) //false

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},[3,4],2]) //false

JSON.stringify([1,{a:1},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //false

JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //true

JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false

JSON.stringify([1,{a:2},[3,4,[4]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false

JSON.stringify([1,{a:2},[3,4,[5]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //true
-1

Я бы сделал следующее:

[2,3,4,5] == [2,3,4,5].toString()

Когда вы используете оператор "==", javascript проверяет, являются ли значения (слева и справа) одним и тем же типом, если он отличается от javascript, попытаться преобразовать обе стороны в один и тот же тип.

Array == String

Array имеет метод toString, поэтому javascript использует его для преобразования их в один и тот же тип, работает так же, как это:

[2,3,4,5].toString() == [2,3,4,5].toString()
  • 0
    Почему проголосовали? можешь хотя бы объяснить?
  • 0
    Потому что вы не удосужились объяснить свой ответ
Показать ещё 3 комментария
-1

Я придумал другой способ сделать это. Используйте join (''), чтобы изменить их на строку, а затем сравнить 2 строки:

var a1_str = a1.join(''),
    a2_str = a2.join('');

if (a2_str === a1_str) {}
  • 3
    Здесь ужасный недосмотр. [1,2,3,4].join('') === [12,34].join('') // => true
  • 0
    Просто используйте .join (','), и он поймает это;)
-1

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

    function isSame(arr1,arr2) {
        var same=true;
        for(var i=0;i < arr1.length;i++) {
            if(!~jQuery.inArray(arr1[i],arr2) || arr1.length!=arr2.length){
                same=false;
                }
            }
        return same;
        }
-2

Работает только для одного уровня Массивы, Строки или Числа

 function isArrayEqual(ar1, ar2) {
     return !ar1.some(item => ar2.indexOf(item) === -1) && ar1.length === ar2.length;
 }
-2

Изображение 2223

Привет, используя метод forEach, вы можете получить ответ всего 2 строки кода

-2
function palindrome(text) 
{
    var Res1 = new Array();
    var Res2 = new Array();
    for (i = 0; i < text.length; i++) 
    {  
            Res1[i] = text.substr(i, 1);        
    } 

    j=0;
for (k = (text.length-1); k>=0; k--) 
    {  
            Res2[j] = text.substr(k, 1);    
            j=j+1;  
    }       

    if(JSON.stringify(Res1)==JSON.stringify(Res2)){
        return true;
    }else{
        return false;
    }
}

document.write(palindrome("katak"));
-2

Кроме того, я преобразовал решение Томаса, чтобы заказать бесплатное сравнение по мере необходимости.

Array.prototype.equalsFreeOrder = function (array) {
    var isThisElemExist;
    if (!array)
        return false;

    if (this.length != array.length)
        return false;

    for (var i = 0; i < this.length; i++) {
        isThisElemExist = false;
        for (var k = 0; k < this.length; k++) {
            if (this[i] instanceof Array && array[k] instanceof Array) {
                if (this[i].equalsFreeOrder(array[k]))
                    isThisElemExist = true;
            }
            else if (this[i] == array[k]) {
                isThisElemExist = true;
            }
        }
        if (!isThisElemExist)
            return false;
    }
    return true;
}
-3
var er = [{id:"23",name:"23222"}, {id:"222",name:"23222222"}];
var er2 = [{id:"23",name:"23222"}, {id:"222",name:"23222222"}];

var result = (JSON.stringify(er) == JSON.stringify(er2)); // true

Он хорошо работает с объектами json, если порядок свойств каждой записи не изменяется.

var er = [{name:"23222",id:"23"}, {id:"222",name:"23222222"}];
var er2 = [{id:"23",name:"23222"}, {id:"222",name:"23222222"}];

var result = (JSON.stringify(er) == JSON.stringify(er2)); // false  

Но в каждой записи массива есть только одно свойство или значение, это будет работать нормально.

-3

JSON.parse также будет проходить через каждое значение, так что, я думаю, было бы лучше сравнить итерацию по каждому значению и уменьшить некоторые этапы выполнения (например, кодировать его в JSON).

-7

Я использую этот код без каких-либо проблем:

if(a.join() == b.join())
    ...

Он работает, даже если в элементе есть запятые.

  • 1
    Запятые в элементе для меня не удаются: ["1", "2"]. join () == ["1,2"]. join ()
  • 1
    ["1", "2"]. Join ('') == ["1,2"]. Join ('') работает.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню