Есть ли в Clojure простой способ конвертации между типами списков? - PullRequest
87 голосов
/ 23 февраля 2011

Я часто использую ленивый список, когда мне нужен вектор, и наоборот.Кроме того, иногда у меня есть вектор карт, когда я действительно хотел набор карт.Существуют ли вспомогательные функции, помогающие мне конвертировать эти типы?

Ответы [ 6 ]

131 голосов
/ 24 февраля 2011

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

(into [] '(1 2 3 4)) ==> [1 2 3 4]         "have a lazy list and want a vector"
(into #{} [1 2 3 4]) ==> #{1 2 3 4}        "have a vector and want a set"
(into {} #{[1 2] [3 4]}) ==> {3 4, 1 2}    "have a set of vectors want a map"
(into #{} [{1 2} {3 4}]) ==> #{{1 2} {3 4}} "have a vector of maps want a set of maps"

into - это обертка вокруг conj, которая является базовой абстракцией для соответствующей вставки новых записей в коллекцию в зависимости от типа коллекции. Принцип, который делает этот поток таким приятным, заключается в том, что Clojure построен на составных абстракциях , в данном случае into поверх conj поверх коллекции и seq.

Приведенные выше примеры все равно будут хорошо составлены, если получатель будет передан во время выполнения: поскольку базовые абстракции (seq и conj) реализованы для всех коллекций (и многих из коллекций Java также), поэтому старшие абстракции не должны беспокоиться о множестве особых случаев, связанных с данными.

31 голосов
/ 23 февраля 2011

vec, set и, как правило, into - ваши друзья могут легко "конвертировать" в другой тип коллекции.

Как вы хотите преобразовать вектор карт в карту карт? Вам нужен ключ, можете ли вы использовать пример ввода / ожидаемого результата?

19 голосов
/ 23 февраля 2011

Для векторов есть функция vec

user=> (vec '(1 2 3))
[1 2 3]

Для ленивых последовательностей есть функция lazy-seq

user=> (lazy-seq [1 2 3])
(1 2 3)

Для преобразования в наборы есть функция set

user=> (set [{:a :b, :c :d} {:a :b} {:a :b}])
#{{:a :b} {:a :b, :c :d}}
12 голосов
/ 01 января 2014

Еще один ответ для преобразования из списка в карту (для полноты) - из здесь :

(apply hash-map '(1 2 3 4))
;=>{1 2, 3 4}
8 голосов
/ 16 ноября 2012

Чтобы преобразовать вектор в список, вы также можете использовать for, например:

=> (for [i [1 2 3 4]] i)
(1 2 3 4)

Если вы не хотите манипулировать данными, просто используйте seq для вектора:

=> (seq [1 2 3])
(1 2 3)
6 голосов
/ 17 декабря 2013

Нет необходимости конвертировать вектор в список. Clojure будет обрабатывать вектор так же, как и список - как последовательность - когда требуется последовательность. Например,

user=> (cons 0 [1 2 3])
(0 1 2 3)

Если вам нужно убедиться, что вектор обрабатывается как последовательность, оберните его в seq:

user=> (conj [1 2 3] 0) ; treated as a vector
[1 2 3 0]

user=> (conj (seq [1 2 3]) 0) ; treated as a sequence
(0 1 2 3)

Если у вас есть вектор карт и вы хотите набор карт, то не имеет значения, что этот вектор содержит карты. Вы просто конвертируете вектор в набор как обычно:

user=> (set [{:a 1, :b 2} {"three" 3, "four" 4}])
#{{:a 1, :b 2} {"four" 4, "three" 3}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...