Когда использовать `zipmap` и когда` map vector`? - PullRequest
23 голосов
/ 26 мая 2011

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

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

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

(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)

Ответы [ 4 ]

37 голосов
/ 26 мая 2011

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

(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 ....)), чтобы получить последовательность пар ключ-значение, а не (вектор карты ...), однако имейте в виду, что это может изменить порядок последовательности ключ-значение пары (поскольку промежуточный хэш-файл неупорядочен)
7 голосов
/ 26 мая 2011

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

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

Редактировать : О, и zipmap не ленив.Так что еще одна причина не использовать его в вашем примере.

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

3 голосов
/ 12 августа 2014

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

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

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

Скажем, мы отображаем две коллекции, 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 map становится последовательностью векторов.

Карта 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.

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

3 голосов
/ 26 мая 2011

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...