Clojure에서 목록 유형간에 쉽게 변환 할 수있는 방법이 있습니까?


92

벡터를 원할 때 lazy list를 사용하는 경우가 많으며 그 반대의 경우도 마찬가지입니다. 또한, 가끔은 맵 세트가 정말로 필요할 때 맵 벡터가 있습니다. 이러한 유형간에 변환하는 데 도움이되는 도우미 함수가 있습니까?

답변:


146

신뢰할 수있는 old into는 seq가능한 모든 것 (list, vector, map, set, sorted-map)과 채우려는 빈 컨테이너를 가져 와서 넣을 수 있다는 것을 잊지 마십시오 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"

intoconj컬렉션 유형에 따라 컬렉션에 새 항목을 적절하게 삽입하기위한 기본 추상화 인 래퍼 입니다. 그래서 친절이 흐름을 만드는 원리는 Clojure의이 빌드에 있다는 것이다 작성 가능 추상화 ,이 경우에는 into위에 conj수집의 상단에 seq.

위의 예는 수신자가 런타임에 전달되는 경우 여전히 잘 구성됩니다. 기본 추상화 ( seq및 conj)가 모든 컬렉션 (및 많은 Java 컬렉션에도 적용됨)에 대해 구현되므로 더 높은 추상화는 걱정할 필요가 없습니다. 많은 특수 데이터 관련 코너 케이스에 대해.


3
에 대한 +1 ... 비어 있지 않은 원래 컨테이너에서도 작동한다는 점에 주목할 가치가 있습니다 (예 : 컬렉션에 추가하려는 경우)
— mikera

11
또한 주목할만한 가치가 있기 때문에 into사용이 conj,하고 (into '() some-seq)의 목록을 얻을 것 반대 때문에, 일부-서열의를 conjconses 목록에.
— Chuck

into대부분의 다른 변환 수단보다 더 나은 성능 특성을 위해 (대부분의 seq 유형에 대해) 과도 현상 을 사용 한다는 점 은 주목할 가치가 있습니다.
— Jarred Humphrey

그리고 이제는이 답변이 작성 될 당시 존재하지 않았던 트랜스 듀서와 함께 작동합니다. (과도 현상도 마찬가지인지 모르겠습니다) (이 답변은 유치원에 등록하기에 충분히 오래되었습니다)
— Arthur Ulfeldt

33

vec, set그리고 일반적으로 into다른 컬렉션 유형으로 쉽게 "변환"할 수있는 친구입니다.

지도 벡터를지도지도로 어떻게 변환 하시겠습니까? 키가 필요합니다. 샘플 입력 / 예상 출력과 함께 사용할 수 있습니까?


죄송합니다.지도 세트를 의미했습니다. 지금 질문을 수정했습니다
— appshare.co

22

벡터의 경우 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}}

4
쓸데없는 간접적 인 지시를 추가하는 lazy-seq대신 지연되지 않은 호출이있을 때 seq. 정말로 당신이 비어 있지 않은 무언가를 반환하고 싶다면 sequence. lazy-seq다소 낮은 수준의 구조입니다.
— cgrand

14

(완전성을 위해) 목록에서 맵으로 변환하는 것에 대한 또 하나의 답변- 여기에서 :

(apply hash-map '(1 2 3 4))
;=>{1 2, 3 4}

9

벡터를 목록으로 변환하려면 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])
— siltalau

7

벡터를 목록 으로 변환 할 필요가 없습니다 . 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}}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.