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 intopozwala ci wziąć wszystko, co jest w seqstanie (lista, wektor, mapa, zestaw, posortowana-mapa) i pusty pojemnik, który chcesz wypełnić, i umieścić intoto.
(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"
intoto 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 intona szczycie conjkolekcji i seq.
Powyższe przykłady nadal dobrze komponowałyby się, gdyby odbiorca był przekazywany w czasie wykonywania: ponieważ bazowe abstrakcje ( seqi 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.
intoużycie conj, działanie (into '() some-seq)da listę, która jest odwrotnością niektórych-seq, ponieważ conjwady na listy.
intowykorzystuje transjenty (dla większości typów sekwencyjnych) w celu uzyskania lepszych charakterystyk wydajności niż większość innych środków konwersji.
vec, seti ogólnie intosą 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 vecfunkcja
user=> (vec '(1 2 3))
[1 2 3]
Dla leniwych sekwencji jest lazy-seqfunkcja
user=> (lazy-seq [1 2 3])
(1 2 3)
Do zamiany na zbiory jest setfunkcja
user=> (set [{:a :b, :c :d} {:a :b} {:a :b}])
#{{:a :b} {:a :b, :c :d}}
lazy-seqzamiast po seqprostu dodaje bezużyteczne pośrednictwo. Jeśli naprawdę chcesz zwrócić coś niezerowego, nawet przed pustą kolekcją, to jest sequence. lazy-seqjest 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 seqna wektorze:
=> (seq [1 2 3])
(1 2 3)
formoż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}}