Когда использовать `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)
Ответы
Ответ 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
.
Это много квалификаторов для двух операций, которые предположительно очень похожи.
Вот почему при принятии решения о том, какой из них следует использовать, необходимо проявлять особую осторожность.
Они очень разные, служат различным целям и не должны использоваться взаимозаменяемо.