diff --git a/README.md b/README.md index 445c41e..07b304f 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ Operations dual to reductions, building lists from seed value rather than consum * [-interpose](#-interpose-sep-list) `(sep list)` * [-interleave](#-interleave-rest-lists) `(&rest lists)` * [-zip-with](#-zip-with-fn-list1-list2) `(fn list1 list2)` -* [-zip](#-zip-list1-list2) `(list1 list2)` +* [-zip](#-zip-rest-lists) `(&rest lists)` * [-first](#-first-pred-list) `(pred list)` * [-last](#-last-pred-list) `(pred list)` * [-first-item](#-first-item-list) `(list)` @@ -1088,12 +1088,14 @@ and the elements from `list2` as `other`. (--zip-with (concat it " and " other) '("Batman" "Jekyll") '("Robin" "Hyde")) ;; => '("Batman and Robin" "Jekyll and Hyde") ``` -#### -zip `(list1 list2)` +#### -zip `(&rest lists)` -Zip the two lists together. Return the list where elements -are cons pairs with car being element from `list1` and cdr being -element from `list2`. The length of the returned list is the -length of the shorter one. +Zip `lists` together. Group the head of each list, followed by the +second elements of each list, and so on. The lengths of the returned +groupings are equal to the length of the shortest input list. + +If two lists are provided as arguments, return the groupings as a list +of cons cells. Otherwise, return the groupings as a list of lists. ```cl (-zip '(1 2 3) '(4 5 6)) ;; => '((1 . 4) (2 . 5) (3 . 6)) @@ -1667,6 +1669,7 @@ Change `readme-template.md` or `examples-to-docs.el` instead. - [Emanuel Evans](https://github.com/shosti) contributed `-if-let`, `-when-let` and `-insert-at`. - [Johan Andersson](https://github.com/rejeep) contributed `-sum`, `-product` and `-same-items?` - [Christina Whyte](https://github.com/kurisuwhyte) contributed `-compose` + - [Steve Lamb](https://github.com/steventlamb) contributed an n-ary version of `-zip` Thanks! diff --git a/dash.el b/dash.el index 9c2a928..8667583 100644 --- a/dash.el +++ b/dash.el @@ -796,12 +796,27 @@ The anaphoric form `--zip-with' binds the elements from LIST1 as `it`, and the elements from LIST2 as `other`." (--zip-with (funcall fn it other) list1 list2)) -(defun -zip (list1 list2) - "Zip the two lists together. Return the list where elements -are cons pairs with car being element from LIST1 and cdr being -element from LIST2. The length of the returned list is the -length of the shorter one." - (-zip-with 'cons list1 list2)) +(defun -zip (&rest lists) + "Zip LISTS together. Group the head of each list, followed by the +second elements of each list, and so on. The lengths of the returned +groupings are equal to the length of the shortest input list. + +If two lists are provided as arguments, return the groupings as a list +of cons cells. Otherwise, return the groupings as a list of lists. " + (let* ((n (-min (-map 'length lists))) + (level-lists (-map (-partial '-take n) lists)) + results) + (while (> n 0) + (let ((split-lists (-map (-partial '-split-at 1) level-lists))) + (setq results (cons (-map 'caar split-lists) results)) + (setq level-lists (-map 'cadr split-lists)) + (setq n (1- n)))) + (setq results (nreverse results)) + (if (= (length lists) 2) + ; to support backward compatability, return + ; a cons cell if two lists were provided + (--map (cons (car it) (cadr it)) results) + results))) (defun -partial (fn &rest args) "Takes a function FN and fewer than the normal arguments to FN, diff --git a/dev/examples.el b/dev/examples.el index 0c4751a..4042630 100644 --- a/dev/examples.el +++ b/dev/examples.el @@ -435,7 +435,9 @@ (defexamples -zip (-zip '(1 2 3) '(4 5 6)) => '((1 . 4) (2 . 5) (3 . 6)) (-zip '(1 2 3) '(4 5 6 7)) => '((1 . 4) (2 . 5) (3 . 6)) - (-zip '(1 2 3 4) '(4 5 6)) => '((1 . 4) (2 . 5) (3 . 6))) + (-zip '(1 2 3 4) '(4 5 6)) => '((1 . 4) (2 . 5) (3 . 6)) + (-zip '(1 2 3) '(4 5 6) '(7 8 9)) => '((1 4 7) (2 5 8) (3 6 9)) + (-zip '(1 2) '(3 4 5) '(6)) => '((1 3 6))) (defexamples -first (-first 'even? '(1 2 3)) => 2 diff --git a/readme-template.md b/readme-template.md index 968b2d5..d3eecb0 100644 --- a/readme-template.md +++ b/readme-template.md @@ -174,6 +174,7 @@ Change `readme-template.md` or `examples-to-docs.el` instead. - [Emanuel Evans](https://github.com/shosti) contributed `-if-let`, `-when-let` and `-insert-at`. - [Johan Andersson](https://github.com/rejeep) contributed `-sum`, `-product` and `-same-items?` - [Christina Whyte](https://github.com/kurisuwhyte) contributed `-compose` + - [Steve Lamb](https://github.com/steventlamb) contributed an n-ary version of `-zip` Thanks!