Я хотел бы сравнить два массива ... в идеале, эффективно. Ничего особенного, только 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 кодирует каждый массив, но есть ли более быстрый или «лучший» способ простого сравнения массивов без необходимости перебирать каждое значение?
javascript
arrays
json
Джулиан Х. Лэм
источник
источник
([] == []) == false
.Ответы:
Чтобы сравнить массивы, просмотрите их и сравните каждое значение:
Сравнение массивов:
Применение:
Вы можете сказать: « Но сравнивать строки гораздо быстрее - никаких циклов ... », тогда вы должны заметить, что есть циклы ARE. Первый рекурсивный цикл, который преобразует массив в строку, а второй, который сравнивает две строки. Так что этот метод быстрее, чем использование строки .
Я считаю, что большие объемы данных всегда должны храниться в массивах, а не в объектах. Однако, если вы используете объекты, их тоже можно частично сравнить.
Вот как:
Сравнение объектов:
Я уже говорил выше, что два экземпляра объекта никогда не будут равны, даже если они на данный момент содержат одинаковые данные:
Это имеет причину, поскольку, например, в объектах могут быть частные переменные.
Однако, если вы просто используете структуру объекта для хранения данных, сравнение все равно возможно:
Однако помните, что этот служит для сравнения данных, подобных JSON, а не экземпляров классов и прочего. Если вы хотите сравнить более сложные объекты, посмотрите на этот ответ, и это сверхдлинная функция .
Чтобы сделать это с
Array.equals
вами, вы должны немного отредактировать оригинальную функцию:Я сделал небольшой тестовый инструмент для обеих функций .
Бонус: вложенные массивы с
indexOf
иcontains
Сэми Бенчериф подготовил полезные функции для случая, когда вы ищете конкретный объект во вложенных массивах, которые доступны здесь: https://jsfiddle.net/SamyBencherif/8352y6yw/
источник
this[i] !== array[i]
вместо!=
.equals
вместоcompare
. По крайней мере, в .NET метод сравнения обычно возвращает подписанное int, указывающее, какой объект больше другого. Смотрите: Сравнить .Хотя это работает только для скалярных массивов (см. Примечание ниже), оно короткое:
Rr, в ECMAScript 6 / CoffeeScript / TypeScript с функциями стрелки:
(Примечание: здесь «скаляр» означает значения, которые можно сравнивать напрямую, используя
===
. Таким образом: числа, строки, объекты по ссылке, функции по ссылке. См. Ссылку MDN для получения дополнительной информации об операторах сравнения).ОБНОВИТЬ
Из того, что я прочитал из комментариев, сортировка массива и сравнение может дать точный результат:
Например:
Тогда приведенный выше код даст
true
источник
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];
не будет работать должным образом)Мне нравится использовать библиотеку Underscore для проектов тяжелого кодирования массивов / объектов ... в Underscore и Lodash, сравниваете ли вы массивы или объекты, это просто выглядит так:
источник
_.isEqual([1,2,3], [2,1,3]) => false
isEqual
функциональность, вы всегда можете использовать модуль_.isEqual([1,2,3].sort(), [2,1,3].sort()) => true
Я думаю, что это самый простой способ сделать это с помощью JSON stringify, и это может быть лучшим решением в некоторых ситуациях:
Это преобразует объекты
a1
иa2
в строки , так что они могут быть сопоставлены. Порядок важен в большинстве случаев, поскольку для этого можно отсортировать объект с помощью алгоритма сортировки, показанного в одном из приведенных выше ответов.Обратите внимание, что вы больше не сравниваете объект, а представляете строковое представление объекта. Это может быть не совсем то, что вы хотите.
источник
Непонятно, что вы подразумеваете под «тождественным». Например, идентичны ли массивы
a
иb
ниже (обратите внимание на вложенные массивы)?Вот оптимизированная функция сравнения массивов, которая сравнивает соответствующие элементы каждого массива по очереди, используя строгое равенство, и не выполняет рекурсивное сравнение элементов массива, которые сами являются массивами, что означает, что для приведенного выше примера
arraysIdentical(a, b)
будет возвращеноfalse
. Он работает в общем случае, который JSON иjoin()
решения не будут:источник
true
. Ответ объясняет, что это не так. Если вам нужно сравнить вложенные массивы, вы можете легко добавить рекурсивную проверку.Практический путь
Я думаю, что неправильно говорить, что конкретная реализация является «Правильным путем», если она только «правильная» («правильная») в отличие от «неправильного» решения. Решение Томаша - это явное улучшение по сравнению со сравнением массивов на основе строк, но это не значит, что оно объективно «правильно». Что правильно в любом случае? Это самый быстрый? Это самый гибкий? Это легче всего понять? Это самый быстрый для отладки? Использует ли он наименьшее количество операций? Есть ли у него побочные эффекты? Ни одно решение не может быть лучшим из всех.
Томаш мог бы сказать, что его решение быстрое, но я бы сказал, что оно слишком сложное. Он пытается быть универсальным решением, которое работает для всех массивов, вложенных или нет. Фактически, он даже принимает в качестве входных данных больше, чем просто массивы, и все еще пытается дать «правильный» ответ.
Дженерики предлагают повторное использование
Мой ответ подойдет к проблеме по-другому. Я начну с общей
arrayCompare
процедуры, которая касается только перехода по массивам. Оттуда мы создадим другие наши базовые функции сравнения, такие какarrayEqual
иarrayDeepEqual
т. Д.На мой взгляд, лучший вид кода даже не нуждается в комментариях, и это не исключение. Здесь так мало всего происходит, что вы можете понять поведение этой процедуры практически без усилий. Конечно, некоторые синтаксисы ES6 могут показаться вам чуждыми, но это только потому, что ES6 является относительно новым.
Как предполагает тип,
arrayCompare
принимает функцию сравненияf
, и два входных массива,xs
иys
. По большей части все, что мы делаем, это вызываемf (x) (y)
каждый элемент во входных массивах. Мы возвращаем досрочно,false
если пользовательскиеf
возвратыfalse
- благодаря&&
оценке короткого замыкания. Так что да, это означает, что компаратор может остановить итерацию на ранней стадии и предотвратить циклическое прохождение через остальную часть входного массива, когда в этом нет необходимости.Строгое сравнение
Затем, используя нашу
arrayCompare
функцию, мы можем легко создавать другие функции, которые могут нам понадобиться. Начнем с элементарногоarrayEqual
…Просто как тот.
arrayEqual
можно определить сarrayCompare
помощью функции сравнения, которая сравниваетсяa
сb
использованием===
(для строгого равенства).Обратите внимание, что мы также определяем
equal
как его собственную функцию. Это подчеркивает рольarrayCompare
функции высшего порядка для использования нашего компаратора первого порядка в контексте другого типа данных (Array).Слабое сравнение
Мы могли бы так же легко определить,
arrayLooseEqual
используя==
вместо этого. Теперь при сравнении1
(Number) с'1'
(String) результат будетtrue
…Глубокое сравнение (рекурсивное)
Вы, наверное, заметили, что это только поверхностное сравнение. Конечно, решение Томаша - «Правильный путь ™», потому что оно подразумевает глубокое сравнение, верно?
Что ж, наша
arrayCompare
процедура достаточно универсальна, чтобы использовать ее таким образом, чтобы сделать тест на глубокое равенство быстрым…Просто как тот. Мы строим глубокий компаратор, используя другую функцию более высокого порядка. На этот раз мы
arrayCompare
используем специальный компаратор, который проверяет, являются ли массивыa
иb
есть ли они. Если это так, повторно применитеarrayDeepCompare
сравнениеa
иb
к указанному пользователем компаратору (f
). Это позволяет нам отделить поведение глубокого сравнения от того, как мы на самом деле сравниваем отдельные элементы. Т.е., как в примере выше показывает, мы можем глубоко сравнить с помощьюequal
,looseEqual
или любой другой компаратор мы делаем.Поскольку
arrayDeepCompare
это карри, мы можем частично применить его так же, как и в предыдущих примерахДля меня это уже явное улучшение по сравнению с решением Томаша, потому что я могу явно выбрать поверхностное или глубокое сравнение для своих массивов, если необходимо.
Сравнение объектов (пример)
А что если у вас есть массив объектов или что-то еще? Может быть, вы хотите считать эти массивы "равными", если каждый объект имеет одинаковое
id
значение ...Просто как тот. Здесь я использовал ванильные объекты JS, но этот тип компаратора может работать для любого типа объекта; даже ваши пользовательские объекты. Решение Томаша должно быть полностью переработано для поддержки такого теста на равенство
Глубокий массив с объектами? Не проблема. Мы создали универсальные, универсальные функции, поэтому они будут работать в самых разных случаях.
Произвольное сравнение (пример)
Или что, если вы хотите провести какое-то совершенно произвольное сравнение? Возможно я хочу знать, больше ли каждый
x
чем каждыйy
…Меньше - больше
Вы можете видеть, что мы на самом деле делаем больше с меньшим количеством кода. В этом нет ничего сложного
arrayCompare
, и каждый из созданных нами пользовательских компараторов имеет очень простую реализацию.С легкостью, мы можем точно определить , как мы хотим , два массива для сравнения - мелкий, глубокий, строгий, свободный, некоторые свойства объекта, или некоторые произвольные вычисления, или любая комбинация из них - все с помощью одной процедуры ,
arrayCompare
. Может быть, даже мечтать оRegExp
компараторе! Я знаю, как дети любят эти регулярные выражения ...Это самый быстрый? Нет. Но это, вероятно, не должно быть либо. Если бы скорость была единственным показателем, используемым для измерения качества нашего кода, было бы выброшено много действительно хорошего кода - вот почему я называю этот подход Практическим путем . Или , может быть более справедливым, Практический подход. Это описание подходит для этого ответа, потому что я не говорю, что этот ответ только практичен по сравнению с некоторым другим ответом; это объективно верно. Мы достигли высокой степени практичности с очень небольшим количеством кода, который очень легко рассуждать. Ни один другой код не может сказать, что мы не заработали это описание.
Это делает это "правильным" решением для вас? Это для вас , чтобы решить. И никто другой не может сделать это для вас; только вы знаете, каковы ваши потребности. Почти во всех случаях я ценю простой, практичный и универсальный код перед умным и быстрым. То, что вы цените, может отличаться, поэтому выберите то, что вам подходит.
редактировать
Мой старый ответ был больше сфокусирован на разложении
arrayEqual
на крошечные процедуры. Это интересное упражнение, но не самый лучший (самый практичный) способ решения этой проблемы. Если вам интересно, вы можете увидеть эту историю изменений.источник
arrayCompare
? Да, функция карри, но она отличается отsome
иevery
.arrayCompare
берет компаратор и два массива для сравнения. Я выбрал конкретно общее имя, потому что мы можем сравнивать массивы, используя любую произвольную функцию. Функция является карри, поэтому она может быть специализированной для создания новых функций сравнения массивов (например,arrayEqual
). Можете ли вы предложить лучшее имя? Какие области, по вашему мнению, требуют дополнительных комментариев или объяснений? Я рад обсудить ^ _ ^В духе оригинального вопроса:
Я проводил тесты производительности на некоторых из более простых предложений, предложенных здесь, со следующими результатами (от быстрого до медленного):
в то время как (67%) Тимом Дауном
каждый (69%) от пользователя2782196
уменьшить (74%) по DEI
присоединиться к & ToString (78%) от Gaizka Альенде & Vivek
половина строки (90%) Виктора Паломо
stringify (100%) от radtek
источник
Array.from({length: 1000}).map((a,v)=>
$ {v}.padStart(10,2));
Опираясь на ответ Томаша Зато, я согласен, что итерация по массивам - самая быстрая. Кроме того (как уже говорили другие), функцию следует называть равной / равной, а не сравнивать. В свете этого я изменил функцию для обработки сравнения массивов на предмет сходства - т.е. они имеют одинаковые элементы, но не по порядку - для личного использования, и подумал, что я добавлю это здесь для всеобщего обозрения.
Эта функция принимает дополнительный параметр strict, который по умолчанию принимает значение true. Этот строгий параметр определяет, должны ли массивы быть полностью одинаковыми как по содержанию, так и по порядку их содержания, или просто содержать одно и то же содержимое.
Пример:
Я также написал быстрый jsfiddle с помощью функции и этого примера:
http://jsfiddle.net/Roundaround/DLkxX/
источник
Несмотря на то, что у этого есть много ответов, я полагаю, что это поможет:
В вопросе о том, как будет выглядеть структура массива, не указано, поэтому если вы точно знаете, что в вашем массиве не будет ни вложенных массивов, ни объектов (это случилось со мной, поэтому я пришел к этому ответьте) приведенный выше код будет работать.
В результате мы используем оператор распространения (...) для объединения обоих массивов, а затем используем Set для устранения любых дубликатов. Если у вас есть это, вы можете сравнить их размеры, если все три массива имеют одинаковый размер, вы можете пойти.
Этот ответ также игнорирует порядок элементов , как я уже сказал, точная ситуация произошла со мной, поэтому, возможно, кто-то в такой же ситуации может оказаться здесь (как я).
Edit1.
Отвечая на вопрос Дмитрия Гринько: «Почему вы использовали оператор распространения (...) здесь - ... новый сет? Он не работает»
Рассмотрим этот код:
Ты получишь
Чтобы работать с этим значением, вам нужно использовать некоторые свойства Set (см. Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set ). С другой стороны, когда вы используете этот код:
Ты получишь
В этом-то и разница: первый дал бы мне набор, он бы тоже работал, так как я мог бы получить размер этого набора, но второй дает мне нужный мне массив, что более непосредственно связано с разрешением.
источник
В тех же строках, что и в JSON.encode, используется join ().
Единственная проблема в том, что вы заботитесь о типах, которые тестирует последнее сравнение. Если вы заботитесь о типах, вам придется зацикливаться.
Если порядок должен оставаться тем же, чем просто цикл, сортировка не требуется.
источник
.join()
. Возможно, если бы вы назвали ваше второе решение первичным (поскольку оно лучше, хотя и беззубое по сравнению с многомерными массивами), я бы не стал судить вас таким образом. До сих пор я преуменьшал все ответы, которые преобразовывают массивы в строки. Кроме того, я проголосовал за всех, кто использует правильный путь, на случай, если вам нужно это знать. Это означает ответ @Tim Down и Bireys один.checkArrays([1,2,3] , ["1,2",3]) == true
и очень маловероятно, что именно этого вы и хотите добиться!join()
как это делает его слегка глючным!Вот версия Typescript:
Некоторые тесты для мокко:
источник
Если вы используете среду тестирования, такую как Mocha, с библиотекой утверждений Chai , вы можете использовать глубокое равенство для сравнения массивов.
Это должно возвращать true, только если массивы имеют равные элементы с соответствующими индексами.
источник
Если они представляют собой два массива чисел или только строки, это быстрый однострочный
источник
[11]
. Довольно очевидно, почему это происходит и как это исправить.В моем случае сравниваемые массивы содержат только цифры и строки. Эта функция покажет вам, если массивы содержат одинаковые элементы.
Давайте проверим это!
источник
are_arrs_equal([1,2], [2,1])
. Кроме того, посмотрите другие обсуждения на этой странице, чтобы узнать, почему строковые функции не нужны, хрупки и неправильны.are_arrs_equal([1,2], [2,1])
возвращается,true
как и ожидалось. Возможно, это решение не идеальное, но оно сработало для меня.are_arrs_match([1,2], ["1,2"])
(возвратtrue
). И обратите внимание, чтоthe sort()
call изменит входные массивы - это может быть нежелательно.Это сравнивает 2 несортированных массива:
источник
Для массива чисел попробуйте:
Показать фрагмент кода
Примечание: этот метод не будет работать, когда массив также содержит строки, например
a2 = [1, "2,3"]
.источник
Мы могли бы сделать это функциональным способом, используя
every
( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every )источник
Ваш код не будет правильно обрабатывать случай, когда оба массива имеют одинаковые элементы, но не в одинаковом порядке.
Посмотрите на мой код с вашим примером, который сравнивает два массива, элементы которых являются числами, вы можете изменить или расширить его для других типов элементов (используя .join () вместо .toString ()).
источник
Вот мое решение:
Работает с любой вложенной структурой данных и, очевидно, игнорирует методы объектов. Даже не думайте о расширении Object.prototype с помощью этого метода, когда я однажды попробовал это сделать, jQuery сломался;)
Для большинства массивов это все же быстрее, чем у большинства решений для сериализации. Это, пожалуй, самый быстрый метод сравнения массивов записей объектов.
источник
equal({}, {a:1})
иequal({}, null)
это ошибки:equal({a:2}, null)
Вот как я это сделал.
источник
Сравнивая 2 массива:
вызывающая функция
источник
Я считаю , что в простом
JS
иECMAScript 2015
, который сладок и прост для понимания.надеюсь, это кому-нибудь поможет.
источник
Расширение идеи Томаша Зато. Array.prototype.compare Томаса должен быть на самом деле Array.prototype.compareIdentical.
Он проходит по:
Но терпит неудачу на:
Вот лучшая (на мой взгляд) версия:
http://jsfiddle.net/igos/bcfCY/
источник
////// ИЛИ ///////
источник
Другой подход с очень небольшим количеством кода (с использованием Array Reduce и Array включает в себя ):
Если вы хотите сравнить также равенство порядка:
В
length
контрольном гарантирует , что множество элементов в одном массиве не является лишь подмножеством другого.Редуктор используется для обхода одного массива и поиска каждого элемента в другом массиве. Если один элемент не найден, возвращается функция уменьшения
false
.источник
Простой подход:
источник
Уже несколько хороших ответов. Но я хотел бы поделиться другой идеей, которая доказала свою надежность при сравнении массивов. Мы можем сравнить два массива, используя JSON.stringify () . Он создаст строку из массива и, таким образом, сравнит две полученные строки из двух массивов на равенство.
источник
Рекурсивно & работает над массивами NESTED :
источник
Работает с НЕСКОЛЬКИМИ аргументами с массивами NESTED :
источник
источник