Я часто использую ленивый список, когда мне нужен вектор, и наоборот. Также иногда у меня есть вектор карт, когда мне очень нужен набор карт. Есть ли какие-нибудь вспомогательные функции, которые помогут мне преобразовать эти типы?
Я часто использую ленивый список, когда мне нужен вектор, и наоборот. Также иногда у меня есть вектор карт, когда мне очень нужен набор карт. Есть ли какие-нибудь вспомогательные функции, которые помогут мне преобразовать эти типы?
Ответы:
Давайте не будем забывать, что надежный старый 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}}