Подтвердить что ты не робот

Когда использовать `zipmap` и когда` map vector`?

Я спрашивал об особенностях конструкции zipmap, чтобы обнаружить, что я, по-видимому, делал это неправильно. Поэтому я узнал о (map vector v u) в этом процессе. Но до этого случая я использовал zipmap для работы (map vector ...). Работало ли оно тогда, потому что результирующая карта была достаточно маленькой, чтобы ее можно было отсортировать?

И к фактическому вопросу: что использовать zipmap, и как/когда его использовать. И когда использовать (map vector ...)?

Моя первоначальная проблема требовала первоначального заказа, поэтому сопоставление ничего не было бы хорошей идеей. Но в основном - кроме порядка получающихся пар - эти два метода эквивалентны, так как отображение seq 'd становится последовательностью векторов.

(for [pair (map vector v (rest v))]
  ( ... )) ;do with (first pair) and (last pair)

(for [pair (zipmap v (rest v))]
 ( ... )) ;do with (first pair) and (last pair)
4b9b3361

Ответ 1

Используйте (zipmap...), когда вы хотите напрямую конструировать hashmap из отдельных последовательностей ключей и значений. Выход представляет собой хэш-карту:

(zipmap [:k1 :k2 :k3] [10 20 40])
=> {:k3 40, :k2 20, :k1 10}

Используйте (вектор карты...), когда вы пытаетесь объединить несколько последовательностей. Вывод представляет собой ленивую последовательность векторов:

(map vector [1 2 3] [4 5 6] [7 8 9])
=> ([1 4 7] [2 5 8] [3 6 9])

Некоторые дополнительные замечания для рассмотрения:

  • Zipmap работает только с двумя входными последовательностями (клавиши + значения), тогда как вектор карты может работать с любым количеством входных последовательностей. Если ваши входные последовательности не являются парами ключевых значений, то это, вероятно, хороший намек на то, что вы должны использовать вектор карты, а не zipmap
  • zipmap будет более эффективным и простым, чем использование вектора карты, а затем создаст хэш-карту из пар ключ/значение - например. (into {} (map vector [:k1 :k2 :k3] [10 20 40])) - довольно запутанный способ сделать zipmap
  • вектор карты ленив - поэтому он приносит немного дополнительных накладных расходов, но очень полезен в обстоятельствах, когда вам действительно нужна лень (например, при работе с бесконечными последовательностями).
  • Вы можете сделать (seq (zipmap....)), чтобы получить последовательность пар ключ-значение, скорее, как (вектор карты...), однако имейте в виду, что это может изменить порядок последовательности значений ключа пары (поскольку промежуточная хэш-карта неупорядочена)

Ответ 2

Методы более или менее эквивалентны. Когда вы используете zipmap, вы получаете карту с парами ключ/значение. Когда вы перебираете эту карту, вы получаете векторы [ключевого значения]. Однако порядок карты не определен. С помощью конструкции "map" в вашем первом методе вы создаете список векторов с двумя элементами. Порядок определяется.

Zipmap может быть немного менее эффективным в вашем примере. Я бы придерживался "карты".

Изменить: О, и zipmap не ленится. Поэтому еще одна причина не использовать его в вашем примере.

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

Ответ 3

(zipmap k v) берет два seqs и возвращает отображение (и не сохраняет порядок элементов)

(вектор карты s1 s2...) принимает любое количество seqs и возвращает seq

используйте первый, когда вы хотите закрепить два раза на карте.

используйте второй, когда вы хотите применить вектор (или список или любую другую форму создания seq) к нескольким seqs.

существует некоторое сходство с опцией "сопоставить" при печати нескольких копий документа:)

Ответ 4

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

  • zipmap создает карту
  • (map vector ...) создает LazySeq n-кортежей (векторы размера n)

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

Скажем, мы сопоставляем две коллекции, coll1 и coll2. Рассмотрим случай, когда coll1 имеет повторяющиеся элементы. Результат zipmap будет содержать только значение, соответствующее последнему виду дубликатов ключей в coll1. Вывод (map vector ...) будет содержать 2-х кортежей со всеми значениями дубликатов ключей.

Простой пример REPL:

=> (zipmap [:k1 :k2 :k3 :k1] [1 2 3 4])
{:k3 3, :k2 2, :k1 4}

=>(map vector [:k1 :k2 :k3 :k1] [1 2 3 4])
([:k1 1] [:k2 2] [:k3 3] [:k1 4])

Имея это в виду, тривиально видеть опасность при принятии следующего:

Но в основном - кроме порядка получающихся пар - эти два метода эквивалентны, так как seq'd-карта становится последовательностью векторов.

Карта seq'd становится последовательностью векторов, но не обязательно той же последовательностью векторов, что и результаты из (map vector ...)

Для полноты здесь отсортированы векторы seq'd:

=> (sort (seq (zipmap [:k1 :k2 :k3 :k1] [1 2 3 4])))
([:k1 4] [:k2 2] [:k3 3])

=> (sort (seq (map vector [:k1 :k2 :k3 :k1] [1 2 3 4])))
([:k1 1] [:k1 4] [:k2 2] [:k3 3])

Я думаю, что самое близкое к тому, что мы можем сделать, например:

Результат set результата (zip map coll1 coll2) будет равен set результата (map vector coll1 coll2), если coll1 сам set.

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