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

Я хотел бы сравнить два массива... в идеале, эффективно. Ничего особенного, просто 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 кодирует каждый массив, но есть ли более быстрый или" лучший " способ просто сравнить массивы без необходимости перебирать каждое значение?

30 ответов


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

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

// Warn if overriding existing method
if(Array.prototype.equals)
    console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's 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;

вы можете сказать:"но гораздо быстрее сравнивать строки - без петель...быстрее, чем использование string.

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

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

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

({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's 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]) {
...

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

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

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


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

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


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

_.isEqual(array1, array2)   // returns a boolean
_.isEqual(object1, object2) // returns a boolean

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

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

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

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


непонятно, что вы подразумеваете под "идентичными". Например, являются массивами 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;
};

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

я думаю, что неправильно говорить, что конкретная реализация - это " правильный путь™", если это только "правильное" ("правильное") в отличие от "неправильного" решения. Решение Томаша является явным улучшением по сравнению со строковым сравнением массивов, но это не означает, что оно объективно "правильно". Что такое право? Это самый быстрый? Он самый гибкий? Это легче всего понять? Это самый быстрый для отладки? Использует ли он наименьшие операции? Делает у него есть побочные эффекты? Ни одно решение не может иметь лучшего из всех.

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


дженерики предлагают возможность повторного использования

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

// 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 to b используя === (строгое равенство).

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


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

мы могли бы так же легко определено arrayLooseEqual С помощью == вместо. Теперь при сравнении 1 (номер) в '1' (строка), результат будет 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

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

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

наши 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 массивы. Если так, apply arrayDeepCompare иначе сравниваем a и b на указанный компаратор (f). Это позволяет нам отделить поведение глубокого сравнения от того, как мы фактически сравниваем отдельные элементы. Т. е., как показано в примере выше, мы можем глубоко сравнить, используя equal, looseEqual, или любой другой компаратор мы делаем.

, потому что 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, но этот тип компаратора мог работа для любой тип объекта; даже пользовательские объекты. Решение Томаша необходимо будет полностью переработать, чтобы поддержать такой тест на равенство

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

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 сам и каждый из пользовательских компараторов, которые мы сделали, имеют очень простую реализацию.

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

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

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


Edit

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


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

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/


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

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

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

пока (67%) by Tim Вниз!--9-->

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

каждый (69%) по user2782196

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

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

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

преобразовать в строки (100%) by radtek

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

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

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


в тех же строках, что и 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

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

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

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

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

это также позаботится о массиве с несоответствующим индексом.


Если вы используете платформу тестирования, например МОКа С чай библиотека утверждений, вы можете использовать глубокий равенство для сравнения массивов.

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

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


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

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

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

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

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

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

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


Edit1.

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

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

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

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


Херер это:

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

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

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


мы могли бы сделать это функциональные способом, используя 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

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

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

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)

расширение идеи Tomáš Zato. Массив Томаса.прототип.compare должен быть вызван массивом infact.прототип.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/


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

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

эта функция сравнивает два массива произвольной формы и 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;
}

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

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


Выберите каждый из [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 
        }
    }
}

JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ?  array.push(collection[i]) : null

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


сравнение 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());

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

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

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


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

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

//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
); 

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


вот версия 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.


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

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

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

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

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