Często znajduję się przy leniwej liście, kiedy chcę mieć wektor i odwrotnie. Czasami mam też wektor map, kiedy bardzo chciałem mieć zestaw map. Czy są jakieś funkcje pomocnicze, które pomogą mi w konwersji między tymi typami?
Często znajduję się przy leniwej liście, kiedy chcę mieć wektor i odwrotnie. Czasami mam też wektor map, kiedy bardzo chciałem mieć zestaw map. Czy są jakieś funkcje pomocnicze, które pomogą mi w konwersji między tymi typami?
Odpowiedzi:
Nie zapominajmy, że zaufany stary into
pozwala ci wziąć wszystko, co jest w seq
stanie (lista, wektor, mapa, zestaw, posortowana-mapa) i pusty pojemnik, który chcesz wypełnić, i umieścić into
to.
(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
to opakowanie wokół conj
, które jest podstawową abstrakcją do wstawiania nowych wpisów odpowiednio do kolekcji w oparciu o typ kolekcji. Zasada, która sprawia, że ten przepływ jest tak przyjemny, polega na tym, że Clojure jest zbudowany na abstrakcyjnych kompozycjach , w tym przypadku into
na szczycie conj
kolekcji i seq
.
Powyższe przykłady nadal dobrze komponowałyby się, gdyby odbiorca był przekazywany w czasie wykonywania: ponieważ bazowe abstrakcje ( seq
i conj
) są zaimplementowane dla wszystkich kolekcji (i wielu kolekcji Javy), więc wyższe abstrakcje nie muszą się martwić o wielu specjalnych przypadkach narożnych związanych z danymi.
into
użycie conj
, działanie (into '() some-seq)
da listę, która jest odwrotnością niektórych-seq, ponieważ conj
wady na listy.
into
wykorzystuje transjenty (dla większości typów sekwencyjnych) w celu uzyskania lepszych charakterystyk wydajności niż większość innych środków konwersji.
vec
, set
i ogólnie into
są Twoimi przyjaciółmi, aby łatwo „przekonwertować” na inny typ kolekcji.
Jak chcesz przekształcić wektor map w mapę map? Potrzebujesz klucza, czy możesz użyć przykładowego wejścia / oczekiwanego wyjścia?
W przypadku wektorów istnieje vec
funkcja
user=> (vec '(1 2 3))
[1 2 3]
Dla leniwych sekwencji jest lazy-seq
funkcja
user=> (lazy-seq [1 2 3])
(1 2 3)
Do zamiany na zbiory jest set
funkcja
user=> (set [{:a :b, :c :d} {:a :b} {:a :b}])
#{{:a :b} {:a :b, :c :d}}
lazy-seq
zamiast po seq
prostu dodaje bezużyteczne pośrednictwo. Jeśli naprawdę chcesz zwrócić coś niezerowego, nawet przed pustą kolekcją, to jest sequence
. lazy-seq
jest w pewnym sensie konstrukcją niskiego poziomu.
Jeszcze jedna odpowiedź na konwersję z listy do mapy (ze względu na kompletność) - stąd :
(apply hash-map '(1 2 3 4))
;=>{1 2, 3 4}
Aby przekonwertować wektor na listę, możesz również użyć for
, na przykład:
=> (for [i [1 2 3 4]] i)
(1 2 3 4)
Jeśli nie chcesz manipulować danymi, po prostu użyj seq
na wektorze:
=> (seq [1 2 3])
(1 2 3)
for
możesz po prostu zrobić(map identity [1 2 3 4])
Nie ma potrzeby przekształcania wektora na listę. Clojure potraktuje wektor tak, jak traktuje listę - jako sekwencję - gdy sekwencja jest wymagana. Na przykład,
user=> (cons 0 [1 2 3])
(0 1 2 3)
Jeśli chcesz się upewnić, że wektor jest traktowany jako sekwencja, zawiń go w 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)
Jeśli masz wektor map i potrzebujesz zestawu map, nie ma znaczenia, że wektor zawiera mapy. Po prostu konwertujesz wektor na zestaw jak zwykle:
user=> (set [{:a 1, :b 2} {"three" 3, "four" 4}])
#{{:a 1, :b 2} {"four" 4, "three" 3}}