Có tương đương với chức năng Zip trong Clojure Core hoặc Contrib không?


130

Trong Clojure, tôi muốn kết hợp hai danh sách để đưa ra danh sách các cặp,

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

Trong Haskell hoặc Ruby, chức năng được gọi là zip . Việc thực hiện nó không khó, nhưng tôi muốn chắc chắn rằng mình không thiếu một chức năng nào trong Core hoặc Contrib.

Có một không gian tên zip trong Core, nhưng nó được mô tả là cung cấp quyền truy cập vào kỹ thuật chức năng Zipper, dường như không phải là thứ tôi đang theo đuổi.

Có một chức năng tương đương để kết hợp 2 danh sách trở lên, theo cách này, trong Core không?

Nếu không có, có phải vì có một cách tiếp cận thành ngữ làm cho chức năng không cần thiết?


Có một zipchức năng trong thư viện Tupelo: cloojure.github.io/doc/tupelo/tupelo.core.html#var-zip
Alan Thompson

Câu trả lời:


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

làm những gì bạn muốn:

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

Haskell cần một tập hợp các hàm zipWith( zipWith3,, zipWith4...), vì tất cả chúng đều phải thuộc một loại cụ thể ; đặc biệt, số lượng danh sách đầu vào mà họ chấp nhận cần phải được sửa. (The zip, zip2, zip3, ... gia đình có thể được coi là một chuyên môn hóa của zipWithgia đình đối với trường hợp sử dụng chung của tupling).

Ngược lại, Clojure và các Lisps khác có hỗ trợ tốt cho các chức năng arity thay đổi; maplà một trong số chúng và có thể được sử dụng để "tupling" theo cách tương tự như của Haskell

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

Cách thành ngữ để xây dựng một "tuple" trong Clojure là xây dựng một vectơ ngắn, như được hiển thị ở trên.

(Chỉ để hoàn chỉnh, lưu ý rằng Haskell với một số tiện ích mở rộng cơ bản không cho phép các chức năng thay đổi; sử dụng chúng đòi hỏi phải hiểu rõ về ngôn ngữ, và vanilla Haskell 98 có thể không hỗ trợ chúng, do đó, các chức năng của arity cố định là thích hợp hơn cho thư viện chuẩn.)


8
Lưu ý rằng điều này hoạt động khác với zipkhi các bộ sưu tập không có cùng độ dài. Ruby sẽ tiếp tục xử lý và cung cấp nils cho bộ sưu tập ngắn hơn, trong khi Clojure sẽ ngừng xử lý khi một trong các bộ sưu tập đã hết.
Nate W.

@NateW. Đó là điều tốt để lưu ý, cảm ơn. Ở Haskell ziphành xử như Clojure mapvề mặt này.
Michał Marc:

1
Tôi có thể yêu cầu một tài liệu tham khảo về các chức năng Haskell arity biến?
Teodor

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

hay nói chung hơn

(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

để cung cấp cho bạn chính xác những gì bạn muốn, ánh xạ listqua hai danh sách sẽ cung cấp cho bạn một danh sách các danh sách như trong ví dụ của bạn. Tôi nghĩ rằng nhiều người Clojurian sẽ có xu hướng sử dụng vectơ cho việc này mặc dù nó sẽ hoạt động với bất cứ điều gì. và các đầu vào không cần phải cùng loại. map tạo seqs từ chúng và sau đó ánh xạ seqs để mọi đầu vào seq'able sẽ hoạt động tốt.

(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
Tôi nghĩ bạn có nghĩa là hash-map và hash-set thay vì map và set.
cgrand

3

Cách tích hợp đơn giản sẽ là chức năng 'xen kẽ':

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

6
để đạt được mục tiêu của OP, bạn nên thêm(partition 2 (interleave [1 2 3 4][5 6 7 8]))
skuro

có - Có vẻ như tôi đã không nhìn vào đầu ra mong muốn của OP quá chặt chẽ.
lsh

-1

Có một hàm gọi là zipmap, có thể có tác dụng tương tự, (zipmap (1 2 3)(4 5 6)) Thông số là dưới dạng fllows: {3 6, 2 5, 1 4}


zipmap trả lại cho bạn một bản đồ, không đảm bảo trật tự
Ilya Shinkarenko

-2

# (áp dụng danh sách bản đồ%) chuyển đổi một ma trận giống như hàm Python zip *. Theo định nghĩa vĩ mô:

người dùng => (defmacro py-zip [lst] `(áp dụng danh sách bản đồ ~ lst))

# 'người dùng / py-zip

người dùng => (py-zip '((1 2 3 4) (9 9 9 9) (5 6 7 8)))

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

người dùng => (py-zip '((1 9 5) (2 9 6) (3 9 7) (4 9 8)))

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


Làm thế nào là tốt hơn so với chỉ sử dụng 'bản đồ'? Và điểm của một macro ở đây là gì?
Dave Newton
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.