Я часто использую ленивый список, когда мне нужен вектор, и наоборот. Также иногда у меня есть вектор карт, когда мне очень нужен набор карт. Есть ли какие-нибудь вспомогательные функции, которые помогут мне преобразовать эти типы?
Давайте не будем забывать, что надежный старый 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), поэтому более высокие абстракции не должны беспокоиться о множестве особых случаев, связанных с данными.
into
использованияconj
, выполнение(into '() some-seq)
приведет к списку, противоположному some-seq, потому что онconj
попадает в списки.into
для улучшения характеристик производительности используются переходные процессы (для большинства типов последовательностей), чем в большинстве других средств преобразования.vec
,set
и, как правилоinto
, ваши друзья легко «конвертируют» в коллекцию другого типа.Как вы хотите преобразовать вектор карт в карту карт? Вам нужен ключ, можете ли вы использовать его с примером ввода / ожидаемого вывода?
источник
Для векторов существует
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}}
источник
lazy-seq
вместо того, чтобыseq
просто добавить бесполезное косвенное обращение . Если вы действительно хотите вернуть что-то ненулевое, даже за пустую коллекцию, то она естьsequence
.lazy-seq
это своего рода конструкция низкого уровня.Еще один ответ для преобразования из списка в карту (для полноты) - отсюда :
(apply hash-map '(1 2 3 4)) ;=>{1 2, 3 4}
источник
Чтобы преобразовать вектор в список, вы также можете использовать
for
, например:=> (for [i [1 2 3 4]] i) (1 2 3 4)
Если вы не хотите манипулировать данными, просто используйте
seq
вектор:=> (seq [1 2 3]) (1 2 3)
источник
for
тебя можно было просто сделать(map identity [1 2 3 4])
Преобразовывать вектор в список не нужно . 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}}
источник