Позвольте A
и B
быть двумя наборами. Я ищу действительно быстрые или элегантные способы вычисления разницы между ними ( A - B
или A \B
, в зависимости от ваших предпочтений). Эти два набора хранятся и обрабатываются как массивы Javascript, как сказано в названии.
Ноты:
- Уловки, специфичные для гекконов, допустимы
- Я бы предпочел придерживаться собственных функций (но я открыт для облегченной библиотеки, если она намного быстрее)
- Я видел, но не тестировал JS.Set (см. Предыдущий пункт)
Изменить: я заметил комментарий о наборах, содержащих повторяющиеся элементы. Когда я говорю «установить», я имею в виду математическое определение, которое означает (среди прочего), что они не содержат повторяющихся элементов.
javascript
arrays
set-difference
Мэтт Болл
источник
источник
indexOf
реализацией.Ответы:
если не знаю, наиболее ли это эффективно, но, возможно, самый короткий
Обновлено до ES6:
источник
!B.includes(x)
вместоB.indexOf(x) < 0
:)Что ж, 7 лет спустя с объектом Set ES6 это довольно просто (но все же не так компактно, как у python
A - B
) и, как сообщается, быстрее, чемindexOf
для больших массивов:источник
Вы можете использовать объект как карту, чтобы избежать линейного сканирования
B
каждого элемента,A
как в ответе user187291 :Нестандартный
toSource()
метод используется для получения уникальных имен свойств; если все элементы уже имеют уникальные строковые представления (как в случае с числами), вы можете ускорить код, отбросивtoSource()
вызовы.источник
Самый короткий, с использованием jQuery, это:
источник
not
больше не работает с универсальными объектами, начиная с версии 3.0.0-rc1. См. Github.com/jquery/jquery/issues/3147Я бы хэшировал массив B, а затем сохранил значения из массива A, отсутствующего в B:
источник
getDifference(a, b, hashOfB)
если он не передан, он будет вычислен, в противном случае он будет повторно использован как есть.Включив идею Кристофа и допустив пару нестандартных методов итерации для массивов и объектов / хэшей (
each
и друзей), мы можем получить разность наборов, объединение и пересечение за линейное время примерно за 20 строк:Это предполагает, что
each
иfilter
определены для массивов, и что у нас есть два служебных метода:myUtils.keys(hash)
: возвращает массив с ключами хешаmyUtils.select(hash, fnSelector, fnEvaluator)
: возвращает массив с результатами вызоваfnEvaluator
пар ключ / значение, для которыхfnSelector
возвращается истина.select()
Свободно вдохновлен Common Lisp, и просто ,filter()
иmap()
в одном лице. (Было бы лучше определить их наObject.prototype
, но это нанесет ущерб jQuery, поэтому я остановился на статических служебных методах.)Производительность: тестирование с
дает два набора по 50 000 и 66 666 элементов. При этих значениях AB занимает около 75 мс, а объединение и пересечение - около 150 мс каждое. (Mac Safari 4.0 с использованием даты Javascript для измерения времени.)
Я считаю, что за 20 строк кода это приличная плата.
источник
hasOwnProperty()
ли элементы числовыми: в противном случае в результирующем наборе никогда не может появиться что-то вродеObject.prototype[42] = true;
средства42
Использование Underscore.js (библиотека для функционального JS)
источник
Некоторые простые функции, заимствованные из ответа @ milan:
Использование:
источник
Что касается быстрого способа, это не так элегантно, но я проверил несколько тестов, чтобы убедиться. Загрузка одного массива как объекта намного быстрее обрабатывать в больших количествах:
Полученные результаты:
Однако это работает только со строками . Если вы планируете сравнивать нумерованные наборы, вам нужно сопоставить результаты с помощью parseFloat .
источник
b.filter(function(v) { return !A[v]; });
во второй функции не должно быть c = ?Это работает, но я думаю, что другой намного короче и элегантнее.
источник