Clojure Core 또는 Contrib에 Zip 기능과 동등한 기능이 있습니까?


130

Clojure에서는 두 목록을 결합하여 쌍 목록을 제공하고 싶습니다.

> (zip '(1 2 3) '(4 5 6))  
((1 4) (2 5) (3 6))

Haskell 또는 Ruby에서는이 기능을 zip 이라고 합니다. 구현하기는 어렵지 않지만 Core 또는 Contrib에서 기능이 누락되지 않았는지 확인하고 싶었습니다.

Core 에는 zip 네임 스페이스가 있지만 Zipper 기능 기술에 대한 액세스를 제공하는 것으로 설명 되어 있지만 나중에는 그렇지 않습니다.

이런 식으로 Core에서 둘 이상의 목록을 결합하는 동등한 기능이 있습니까?

그렇지 않은 경우, 함수를 불필요하게 만드는 관용적 접근 방식이 있습니까?


zipTupelo 라이브러리 에는 다음과 같은 기능이 있습니다. cloojure.github.io/doc/tupelo/tupelo.core.html#var-zip
Alan Thompson

답변:


220
(map vector '(1 2 3) '(4 5 6))

당신이 원하는 것을합니까 :

=> ([1 4] [2 5] [3 6])

Haskell은 zipWith( zipWith3,, zipWith4...) 함수 모음이 필요 합니다. 왜냐하면 모두 특정 유형 이어야하기 때문입니다 . 특히, 입력 목록의 수는 고정되어야합니다. 합니다 ( zip, zip2, zip3, ...은 가족의 특성화로 간주 될 수 zipWithtupling의 일반적인 사용을위한 가정).

반대로 Clojure와 다른 Lisp는 다양한 arity 기능을 잘 지원합니다. map그 중 하나이며 Haskell과 유사한 방식으로 "터플 링"에 사용될 수 있습니다.

zipWith (\x y -> (x, y))

Clojure에서 "튜플"을 만드는 관용적 방법은 위에 표시된 것처럼 짧은 벡터를 구성하는 것입니다.

(완전성을 위해 일부 기본 확장 기능을 가진 Haskell은 가변 arity 기능을 허용하지만 언어를 잘 이해해야하지만 바닐라 Haskell 98은 전혀 지원하지 않으므로 고정 arity 기능을 선호합니다 표준 라이브러리.)


8
zip컬렉션 길이가 동일하지 않은 경우와 다르게 동작 합니다. Ruby는 nil더 짧은 컬렉션에 대한 처리 및 공급을 계속하는 반면 Clojure는 컬렉션 중 하나가 소진되면 처리를 중지합니다.
Nate W.

@NateW. 감사합니다. Haskell에서는 이와 관련하여 zipClojure처럼 행동 map합니다.
Michał Marczyk 2016 년

1
변수 arity Haskell 함수에 대한 참조를 요청할 수 있습니까?
Teodor

22
(partition 2 (interleave '(1 2 3) '(4 5 6))) 
=> ((1 4) (2 5) (3 6))

또는 더 일반적으로

(defn zip [& colls]
  (partition (count colls) (apply interleave colls)))

(zip '( 1 2 3) '(4 5 6))           ;=> ((1 4) (2 5) (3 6))

(zip '( 1 2 3) '(4 5 6) '(2 4 8))  ;=> ((1 4 2) (2 5 4) (3 6 8))


11

정확히 원하는 것을 제공하기 위해 list두 목록을 매핑 하면 예제와 같이 목록 목록이 제공됩니다. 많은 Clojurians가 이것을 위해 벡터를 사용하는 경향이 있다고 생각합니다. 입력이 같은 유형일 필요는 없습니다. map은 그들로부터 seq를 만든 다음 seq를 매핑하여 seq'able 입력이 정상적으로 작동합니다.

(map list '(1 2 3) '(4 5 6))
(map list  [1 2 3] '(4 5 6))
(map hash-map  '(1 2 3) '(4 5 6))
(map hash-set  '(1 2 3) '(4 5 6))

1
나는 당신이 map과 set 대신 hash-map과 hash-set을 의미한다고 생각합니다.
cgrand

3

내장 된 방법은 단순히 'interleave'함수입니다.

(interleave [1 2 3 4] [5 6 7 8]) => [1 5 2 6 3 7 4 8]

6
OP의 목표를 달성하기 위해 추가해야합니다(partition 2 (interleave [1 2 3 4][5 6 7 8]))
skuro

예-OP의 원하는 출력을 너무 자세히 보지 않은 것 같습니다.
lsh

-1

zipmap이라는 함수가 있는데, 비슷한 효과를 낼 수 있습니다. (zipmap (1 2 3)(4 5 6)) 출력값은 다음과 같습니다. {3 6, 2 5, 1 4}


zipmap은 주문을 보장하지 않는지도를 반환합니다.
Ilya Shinkarenko

-2

# (apply map list %)는 Python zip * 함수와 같은 행렬을 바꿉니다. 매크로 정의로 :

user => (defmacro py-zip [lst]`(지도 목록 적용 ~ lst))

# '사용자 / py-zip

user => (py-zip '((12 34 9) (5 6 7 8)))

((1 9 5) (2 9 6) (3 9 7) (4 9 8))

user => (py-zip '((1 9 5) (2 9 6) (3 9 7) (4 9 8)))

((12 34) (9 9 9 9) (5 6 7 8))


'지도'를 사용하는 것보다 어떻게 더 낫습니까? 그리고 매크로의 요점은 무엇입니까?
Dave Newton
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.