У меня есть два таких набора результатов:
// Result 1
[
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
{ value: "4", display: "Ryan" }
]
// Result 2
[
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
]
Конечный результат, который мне нужен, - это разница между этими массивами - конечный результат должен быть таким:
[{ value: "4", display: "Ryan" }]
Можно ли сделать что-то подобное в JavaScript?
Ответы:
Используя только собственный JS, будет работать что-то вроде этого:
источник
return a.value ===...
в вашем ответе? (Хорошее решение, кстати, +1) Кроме использованияArray.prototype.some()
, я не могу найти более эффективный / более короткий способ сделать это.true
илиfalse
значение). В этом случае, если мы отделим понятие проверки на равенство от остальной части кода, потребовав от пользователя пройти проверку на равенство как функцию, мы можем сделать простой общий алгоритм.Вы можете использовать
Array.prototype.filter()
в сочетании сArray.prototype.some()
.Вот пример (при условии, что ваши массивы хранятся в переменных
result1
иresult2
):источник
Для тех, кто любит однострочные решения в ES6, примерно так:
источник
Я придерживаюсь чуть более универсального подхода, хотя по идее он похож на подходы @Cerbrus и @Kasper Moerch . Я создаю функцию, которая принимает предикат, чтобы определить, равны ли два объекта (здесь мы игнорируем
$$hashKey
свойство, но это может быть что угодно) и возвращаю функцию, которая вычисляет симметричную разность двух списков на основе этого предиката:У него есть одно небольшое преимущество перед подходом Церебруса (как и подход Каспера Мёрча) в том, что он ускользает раньше; если он находит совпадение, он не утруждает себя проверкой остальной части списка. Если бы у меня была под
curry
рукой функция, я бы сделал это немного по-другому, но это нормально работает.Объяснение
В комментарии для начинающих просили более подробное объяснение. Вот попытка.
Мы передаем следующую функцию
makeSymmDiffFunc
:С помощью этой функции мы решаем, что два объекта равны. Как и все функции, возвращающие
true
илиfalse
, ее можно назвать «функцией предиката», но это всего лишь терминология. Главное, чтоmakeSymmDiffFunc
настроена функция, которая принимает два объекта и возвращает,true
если мы считаем их равными,false
если нет.Используя это,
makeSymmDiffFunc
(читайте "сделать симметричную функцию разности") возвращает нам новую функцию:Это функция, которую мы фактически будем использовать. Мы передаем ему два списка, и он находит элементы из первого, а не из второго, затем элементы из второго, а не из первого, и объединяет эти два списка.
Однако, просматривая это еще раз, я определенно мог взять реплику из вашего кода и немного упростить основную функцию, используя
some
:complement
использует предикат и возвращает элементы первого списка, а не второго. Это проще, чем мой первый проход с отдельнойcontains
функцией.Наконец, основная функция заключена в выражение немедленно вызываемой функции ( IIFE ), чтобы внутренняя
complement
функция не попадала в глобальную область видимости.Обновление, несколько лет спустя
Теперь, когда ES2015 стал довольно широко распространенным, я бы предложил ту же технику, но с гораздо меньшим количеством шаблонов:
источник
Это вернет разницу между двумя массивами объектов, используя ключ
value
для их сравнения. Обратите внимание, что две вещи с одинаковым значением не будут возвращены, так как другие ключи игнорируются.Это часть lodash .
источник
Вы можете создать объект с ключами в качестве уникального значения, соответствующего каждому объекту в массиве, а затем отфильтровать каждый массив на основе наличия ключа в другом объекте. Это снижает сложность операции.
ES6
ES5
источник
Я думаю, что решение @Cerbrus подходит. Я реализовал то же решение, но извлек повторяющийся код в свою собственную функцию (DRY).
источник
Я нашел это решение, используя фильтр и некоторые другие.
источник
Большинство ответов здесь довольно сложные, но разве логика этого не проста?
O (n ^ 2) сложность.
источник
вы можете сделать diff a на b и diff b на a, а затем объединить оба результата
источник
Я сделал обобщенное сравнение, которое сравнивает 2 объекта любого типа и может запустить обработчик модификации gist.github.com/bortunac "diff.js" , например, используя:
поэтому свойство a изменено, b удалено, c изменено, d добавлено
}
теперь используйте как
консоль покажет
источник
Самый общий и простой способ:
источник
Когда дело касается больших массивов, я предпочитаю объект карты.
источник
В JavaScript есть карты, которые обеспечивают время вставки и поиска O (1). Следовательно, это можно решить за O (n) (а не за O (n²), как это делают все другие ответы). Для этого необходимо сгенерировать уникальный ключ-примитив (строка / число) для каждого объекта. Можно
JSON.stringify
, но это довольно подвержено ошибкам, поскольку порядок элементов может влиять на равенство:Поэтому я бы взял разделитель, которого нет ни в одном из значений, и вручную составил бы строку:
Затем создается карта. Когда элемент уже существует на карте, он удаляется, в противном случае он добавляется. Следовательно, остаются только элементы, которые включены нечетное время (то есть только один раз). Это будет работать, только если элементы в каждом массиве уникальны:
Показать фрагмент кода
источник
Я столкнулся с этим вопросом, ища способ выбрать первый элемент в одном массиве, который не соответствует ни одному из значений в другом массиве, и мне удалось в конечном итоге отсортировать его с помощью array.find () и array.filter (), например этот
если вам нужно продолжать получать обновленный список перед перекрестной проверкой следующего лучшего варианта, это должно работать достаточно хорошо :)
источник
Если вы хотите использовать внешние библиотеки, для этого можно использовать _.difference в underscore.js. _.difference возвращает значения из массива, которых нет в других массивах.
источник