Итерация и сравнение Javascript [дубликат]

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

TypeA objA;

. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException, что имеет смысл.

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
706
задан user633183 4 October 2015 в 22:21
поделиться

31 ответ

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

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

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

Вы можете сказать: « Но гораздо проще сравнивать строки - нет петель ... « ну, тогда вы должны отметить, что есть циклы 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's say YES
    return true;
}  

Однако помните, что этот метод служит для сравнения JSON как данных, а не экземпляров классов и других вещей. Если вы хотите сравнить более сложные объекты, посмотрите на этот ответ, и это суперлайновая функция . Чтобы выполнить эту работу с 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

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

725
ответ дан Rob Bednark 20 August 2018 в 09:23
поделиться
  • 1
    Если вы хотите выполнять строгие сравнения, используйте this[i] !== array[i] вместо !=. – Tim S. 15 May 2013 в 14:19
  • 2
    Ваш метод следует называть equals вместо compare. По крайней мере, в .NET сравнение обычно возвращает подписанный int, указывающий, какой объект больше, чем другой. См. Comparer.Compare . – Oliver 31 May 2013 в 13:24
  • 3
    Nt только это правильный способ сделать это, это также значительно более эффективно. Вот быстрый сценарий jsperf, который я подготовил для всех методов, предложенных в этом вопросе. jsperf.com/comparing-arrays2 – Tolga E 16 October 2013 в 20:30
  • 4
    Изменение прототипа встроенного типа, безусловно, не является правильным способом – Jasper 14 August 2014 в 10:29
  • 5
    Кроме того, речь идет не о том, легко ли переписать, речь идет о том, что ответ не должен рекомендовать что-то, что считается плохой практикой ( developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/&hellip ; ), и если определенно не делает этого ниже заголовка & quot; Правильный путь & quot; – Jasper 1 September 2014 в 10:07

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

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 для получения дополнительной информации о операторах сравнения).

UPDATE

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

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

235
ответ дан Abhi 20 August 2018 в 09:23
поделиться
  • 1
    Мне это нравится, хотя читатели должны знать, что это работает только на отсортированных массивах. – Ellen Spertus 15 December 2013 в 17:05
  • 2
    Он работает с любыми типами массивов, отсортированными или нет @espertus – Michał Miszczyszyn 24 March 2016 в 15:03
  • 3
    Да, точно. Эта функция должна сравнивать два массива, неважно, отсортированы они или нет, их последовательные элементы должны быть равны. – Michał Miszczyszyn 26 March 2016 в 01:39
  • 4
    @espertus Действительно, он не вернет true, если элементы не имеют одинакового порядка в обоих массивах. Тем не менее, цель проверки равенства заключается не в том, чтобы проверить, содержат ли они одни и те же элементы, а для проверки того, имеют ли они один и тот же элемент в одних и тех же заказах. – Quentin Roy 6 June 2016 в 03:25
  • 5
    Если вы хотите проверить, равны ли оба массива равными, содержащими одинаковые несортированные элементы (но не используемые несколько раз), вы можете использовать a1.length==a2.length && a1.every((v,i)=>a2.includes(v)): var a1 =[1,2,3], a2 = [3,2,1]; (var a1 =[1,3,3], a2 = [1,1,3]; не будет работать должным образом) – mems 21 November 2016 в 16:25

Сравнение 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());
1
ответ дан Amay Kulkarni 20 August 2018 в 09:23
поделиться
  • 1
    Этот ответ не будет работать, так как === не ведет себя так, как ожидалось для массивов. – Michael Yang 27 February 2018 в 05:20
  • 2
    Ответ работает, хотя === не имеет никакого значения здесь (поскольку sort () работает только с массивом). Даже == также будет работать. – Amay Kulkarni 28 February 2018 в 15:14
  • 3
    Попробуйте сами; он печатает false, если вы запустите этот код. Это происходит из-за сравнения опорных значений массивов как с символами == и ===, так и с их фактическими значениями. == и === предназначены только для примитивного сравнения типов. – Michael Yang 3 March 2018 в 21:32
  • 4
    Он возвращает true, мы его использовали, но теперь я удалил '===', поскольку он не является необязательным – Amay Kulkarni 13 March 2018 в 11:12
  • 5
    Ах, я не заметил, что вы конвертировали в строку и вызывали функцию после сортировки и присоединения; мои извинения. – Michael Yang 20 March 2018 в 07:52

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

_.isEqual(array1, array2)   // returns a boolean
_.isEqual(object1, object2) // returns a boolean
154
ответ дан Beau Smith 20 August 2018 в 09:23
поделиться
  • 1
    Обратите внимание, что порядок имеет значение _.isEqual([1,2,3], [2,1,3]) => false – Vitaliy Alekask 18 August 2015 в 13:23
  • 2
    или если вы хотите только функциональность isEqual, вы всегда можете использовать модуль lodash.isequal – hellatan 18 February 2016 в 16:36
  • 3
    Вы можете использовать _.difference (); если заказ не имеет значения для вас – Ronan Quillevere 31 March 2017 в 15:00
  • 4
    Мы можем отсортировать массив до этой проверки, если порядок не имеет значения _.isEqual([1,2,3].sort(), [2,1,3].sort()) => true – Filype 2 June 2017 в 11:30

Эта функция сравнивает два массива произвольной формы и 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
ответ дан chessweb 20 August 2018 в 09:23
поделиться

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

Я бы хотел сравнить два массива ... идеально, эффективно.

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

, а (67%) - 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);

join & amp; toString (78%) Gaizka Allende & amp; vivek

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

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

half toString (90%) от Victor Palomo

a1 == a2.toString();

stringify (100%) на radtek

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

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

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

24
ответ дан Community 20 August 2018 в 09:23
поделиться

В тех же строках, что и 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
5
ответ дан epascarello 20 August 2018 в 09:23
поделиться
  • 1
    Это работает только для определенных массивов и будет очень медленным с большими массивами. – Tomáš Zato 21 March 2013 в 23:01
  • 2
    Генерация JSON тоже зацикливается, вы просто (или, похоже, так) не знаете об этом. Помимо цикла, генерация JSON также требует больше памяти - перед сопоставлением она создает 2 строковых представления указанных массивов. Функция downwote реализована для того, чтобы отвечать на запросы от лучших до худших. Я думаю, что ваш ответ не является хорошим ответом, поэтому я отказался от него. – Tomáš Zato 22 March 2013 в 00:08
  • 3
    Извините, я просто сказал JSON вместо .join(). Возможно, если бы вы заявили, что ваше второе решение является первичным (так как оно лучше, но беззубым против многомерных массивов), я бы не стал так вас судить. До сих пор я перебросил все ответы, которые преобразуют массивы в строки. Кроме того, я поддержал все, что использует правильный путь, если вам это нужно знать. Это означает ответ @Tim Down и Bireys one. – Tomáš Zato 22 March 2013 в 01:01
  • 4
    Первая версия FAILS: checkArrays([1,2,3] , ["1,2",3]) == true, и очень маловероятно, что это то, что вы хотите! – Doin 16 October 2014 в 04:46
  • 5
    @epascarello: Да, вы можете, но (помимо неэффективности очень длинного разделителя, который вы предлагаете), это означает, что будут случаи с краем (где массив содержит строку с вашим разделителем в ней), где функция checkArrays () ошибочна , Это может быть не проблема, если вы знаете что-то о содержимом массивов (поэтому вы можете выбрать разделитель, который, как вы уверены, не будет в элементах массива), но если вы пытаетесь написать general , тогда использование join(), как это делает его тонко багги! – Doin 17 October 2014 в 14:49

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

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

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

27
ответ дан Evan Steinkerchner 20 August 2018 в 09:23
поделиться

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

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
5
ответ дан Gaizka Allende 20 August 2018 в 09:23
поделиться
  • 1
    const array1 = [1]; const array2 = [1, 1]; console.log (array1.join ('') === array2.join ('')) // возвращает true – Dan M. 7 May 2017 в 17:58
  • 2
    он не должен: array1.join ('') равен '1', а array2.join ('') - '11' – Gaizka Allende 9 May 2017 в 05:27
  • 3
    извините, опечатка. Первый массив должен быть [11]. Довольно очевидно, почему это происходит и как исправить. – Dan M. 10 May 2017 в 02:21
  • 4
    Не уверен, о чем вы, это довольно просто: [1] .join () is & quot; 1 & quot; и [1,1] .join () является «1,1», поэтому они никогда не будут равны – Gaizka Allende 11 May 2017 в 15:01
  • 5
    пожалуйста, внимательно прочитайте мой комментарий. Если вы все еще не видите этого, пожалуйста, возьмите добычу в ideone.com/KFu427 – Dan M. 11 May 2017 в 15:24

Решение Herer:

/**
 * 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 сломался;)

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

3
ответ дан Harry 20 August 2018 в 09:23
поделиться
  • 1
    не хорошо! они дают true: equal({}, {a:1}) и equal({}, null), и эти ошибки отсутствуют: equal({a:2}, null) – kristianlm 3 February 2017 в 14:05

Расширение идеи Томаша Зато. 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/

1
ответ дан Igor S. 20 August 2018 в 09:23
поделиться
  • 1
    -1. Если на примере, который вы дали, он «терпит неудачу», тогда это только случай для произвольного определения «fail». Почему вы ожидаете, что эти два разных массива будут считаться равными? Вы даже не объяснили, какую концепцию «равенства» вы пытаетесь реализовать здесь, или почему это разумный или полезный, но похоже, что вы хотите сравнить многомерные массивы, как если бы они были свернуты до одномерных из них. Если это так, вы даже этого не достигли: [1,2] .compare ([[1,2]]) дает ложную версию, как и у Томаша. – Mark Amery 8 June 2013 в 14:57
  • 2
    Исходя из того, что я мог сделать, он говорит, что [1, 2, 3, 4] и [1, 3, 2, 4] следует сравнивать как равные (порядок не имеет значения). – Gautham Badhrinathan 3 July 2013 в 09:50
  • 3
    Я согласен, что обе версии удовлетворяют различным определениям «равно», но я не думаю, что это должно быть -1, так что +1 от меня – OrganicPanda 26 July 2013 в 09:47

Выберите каждый из [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
ответ дан jclobro 20 August 2018 в 09:23
поделиться

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

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

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

4
ответ дан Jeferson Euclides 20 August 2018 в 09:23
поделиться
  • 1
    Почему вы использовали оператор распространения (...) здесь - ... новый Set? Это не работает. – Dmitry Grinko 9 November 2017 в 20:34
  • 2
    Дмитрий Гринько, я верю, что ответил на ваш вопрос в своем Edit1. Но я не уверен, что вы имели в виду, говоря «это не работает», так как оба ответа могут помочь вам – Jeferson Euclides 10 November 2017 в 12:37
  • 3
    блестящий! .... – Toolkit 1 December 2017 в 13:32
JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ?  array.push(collection[i]) : null

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

1
ответ дан Leed 20 August 2018 в 09:23
поделиться
  • 1
    Хорошее решение - но я задаюсь вопросом в некоторых ситуациях, если он не всегда будет работать так, как предполагалось, например, с некоторыми примитивами или глубоко вложенными массивами? Я надеюсь, что он работает при любых обстоятельствах, хотя – Ben Rondeau 13 December 2017 в 22:37
  • 2
    Я не уверен, работает ли он во вложенных массивах. – Leed 14 December 2017 в 01:47

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

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

1
ответ дан ludico8 20 August 2018 в 09:23
поделиться

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

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

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

5
ответ дан metakermit 20 August 2018 в 09:23
поделиться

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

function areEqual(a, b) {
  if ( a.length != b.length) {
    return false;
  }
  return a.filter(function(i) {
    return !b.includes(i);
  }).length === 0;  
}
3
ответ дан Nathan Boolean Trujillo 20 August 2018 в 09:23
поделиться

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

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
ответ дан Omar Elawady 20 August 2018 в 09:23
поделиться

Мы могли бы сделать это функциональным способом, используя 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
ответ дан peonicles 20 August 2018 в 09:23
поделиться

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

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

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

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

59
ответ дан radtek 20 August 2018 в 09:23
поделиться
  • 1
    хороший ответ, но почему [] == [] возвращает false? тогда как простые объекты, то почему? – Pardeep Jain 17 January 2016 в 20:03
  • 2
    @PardeepJain, это потому, что по умолчанию оператор равенства в ECMAScript для объектов возвращает true, когда они ссылаются на одну и ту же ячейку памяти. Попробуйте var x = y = []; // теперь равенство возвращает true. – radtek 17 January 2016 в 20:52
  • 3
    просто отметить, что функция JSON stringify не быстро. Используется с большими массивами, безусловно, будет вводить задержку. – Lukas 29 April 2017 в 11:03
  • 4
    Вопрос конкретно задает вопрос, существует ли способ лучше / быстрее , чем использование JSON.stringify. – Don Hatch 10 May 2017 в 01:02
  • 5
    Он более подробно описывает, почему это может быть хорошим решением для некоторых ситуаций. – radtek 11 May 2017 в 21:30

Неясно, что вы подразумеваете под «идентичными». Например, массивы 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;
};
60
ответ дан Tim Down 20 August 2018 в 09:23
поделиться
  • 1
    @ASDF: непонятно из вопроса, что "идентично" означает. Очевидно, что этот ответ делает мелкую проверку. Я добавлю примечание. – Tim Down 4 September 2014 в 14:33
  • 2
    это не удается для массивовIdentical ([1, 2, [3, 2]], [1, 2, [3, 2]]); – Gopinath Shiva 31 July 2015 в 13:08
  • 3
    @GopinathShiva: Ну, это только терпит неудачу, если вы ожидаете, что он вернется true. Ответ объясняет, что это не так. Если вам нужно сравнить вложенные массивы, вы можете легко добавить рекурсивную проверку. – Tim Down 31 July 2015 в 23:16

Мое решение сравнивает объекты, а не массивы. Это будет работать так же, как 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;
}

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

0
ответ дан user1877408 20 August 2018 в 09:23
поделиться
40
ответ дан user633183 20 August 2018 в 09:23
поделиться
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)
2
ответ дан Vasanth 20 August 2018 в 09:23
поделиться
  • 1
    Вы можете также использовать какую-либо функцию, которая не будет полностью переименовываться, если мы получим требуемое условие, как указано выше – Vasanth 8 March 2017 в 15:42

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

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

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

5
ответ дан Vivek 20 August 2018 в 09:23
поделиться
  • 1
    Вы можете использовать строгую проверку равенства === (чтобы сделать linter happy), если соответствующие массивы содержат строковые элементы. – TranslucentCloud 31 March 2017 в 11:44
  • 2
    Не работает [1,2] и ["1,2"]. Обратите внимание, что вызов the sort() будет изменять входные массивы - это может быть нежелательно. – try-catch-finally 15 July 2017 в 08:51
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
ответ дан macki 20 August 2018 в 09:23
поделиться

Вот версия 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
ответ дан Martin 20 August 2018 в 09:23
поделиться

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

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

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

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

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

0
ответ дан Mator 20 August 2018 в 09:23
поделиться

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

//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
ответ дан Serge 20 August 2018 в 09:23
поделиться
  • 1
    карта, уменьшить, фильтровать все! :П – Thoran 16 July 2016 в 12:56
  • 2
    Это плохое решение, потому что Array.prototype.reduce будет проходить каждый элемент в a, даже если первые сравниваемые элементы не совпадают. Кроме того, использование !a и != в цикле является двойным отрицательным, что делает этот ответ более сложным (и трудно читаемым), чем нужно – user633183 7 August 2016 в 15:39
  • 3
    Согласен. Есть некоторая функция some () :) Два года назад я этого не знал. Но двойное отрицание все равно будет. – Serge 8 August 2016 в 15:58

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

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
ответ дан yesnik 20 August 2018 в 09:23
поделиться
  • 1
    Вопрос не просит вас сортировать, поэтому ваше решение неверно для таких примеров, как are_arrs_equal([1,2], [2,1]). Кроме того, см. Другие обсуждения на этой странице, почему сборка является ненужной, хрупкой и неправильной. – phyzome 3 August 2016 в 03:31
  • 2
    are_arrs_equal([1,2], [2,1]) возвращает true, как ожидалось. Возможно, это решение не идеально, но это сработало для меня. – yesnik 8 August 2016 в 12:37
  • 3
    Это как раз проблема, эти два не равны в каком-либо здравом смысле слова «равный». для упорядоченной структуры данных . Это массивы, а не набор, и если вы хотите установить равенство, вы должны это назвать - и отвечать на другой вопрос. :-) – phyzome 9 August 2016 в 19:59
  • 4
    Я согласен с комментариями выше, но это решение также работает для меня в простых массивах целых чисел, где порядок не важен, поэтому я буду использовать его. – tomazahlin 14 October 2016 в 16:51
  • 5
    Не работает are_arrs_match([1,2], ["1,2"]) (возвращает true). Обратите внимание, что вызов the sort() будет изменять входные массивы - это может быть нежелательно. – try-catch-finally 15 July 2017 в 08:38
Другие вопросы по тегам:

Похожие вопросы: