首先,對於只有2只列出了工作的簡單的迭代版本:
(define (zip lst1 lst2 (placeholder '()))
(define (my-car lst)
(if (empty? lst) placeholder (car lst)))
(define (my-cdr lst)
(if (empty? lst) lst (cdr lst)))
(let loop ((lst1 lst1) (lst2 lst2) (res '()))
(if (and (empty? lst1) (empty? lst2))
(reverse res)
(loop (my-cdr lst1) (my-cdr lst2)
(cons (list (my-car lst1) (my-car lst2)) res)))))
如
(zip '(a b c) '(1 2 3))
=> '((a 1) (b 2) (c 3))
(zip '(a b c) '(1))
=> '((a 1) (b()) (c()))
這個,你可以概括爲n的列表,但要避免關鍵字參數必須先放置佔位符參數:
(define (zip placeholder . lsts)
(define (my-car lst)
(if (empty? lst) placeholder (car lst)))
(define (my-cdr lst)
(if (empty? lst) lst (cdr lst)))
(let loop ((lsts lsts) (res '()))
(if (andmap empty? lsts)
(reverse res)
(loop (map my-cdr lsts)
(cons (apply list (map my-car lsts)) res)))))
如
(zip '() '(a b c) '(1 2 3))
==> '((a 1) (b 2) (c 3))
(zip '() '(a b c) '(1))
==> '((a 1) (b()) (c()))
(zip '() '(a b c) '(1) '(x y))
=> '((a 1 x) (b() y) (c()()))
我相信andmap是這裏唯一特定拍功能,它可能有一些計劃或SRFI等值積分,取決於您的實現。
編輯
由於該解決方案的基礎是創建等長的名單,而不是複製壓縮算法,也可以先做經典地圖列表東西前添加佔位符列表:
(define (zip placeholder . lsts)
(let* ((max-len (apply max (map length lsts))) ; the length of the longest lists
(equal-length-lists ; adjusts all lists to the same length,
(map ; filling with placeholder
(lambda (lst) (append lst (make-list (- max-len (length lst)) placeholder)))
lsts)))
(apply map list equal-length-lists))) ; classical zip
你想做什麼不清楚。您想要的結果沒有正確鍵入:第一個列表由一個符號和一個整數組成,後兩個列表由一個符號和一個列表組成。這是可能的,但不太可能。一個更好的表達式(zip'(a b c)'(1))將返回((a 1))並放棄多餘的項目,或者返回((a 1)(b)(c))。當zip函數有三個或更多的列表時,你會做什麼?請明確說明你想要做什麼。 – user448810
我想要在兩個列表之間進行映射,如果列表是偶數,那麼每個項目都映射到其他列表中項目的相同索引,例如(zip'(abc)'(1 2 3))=>( (a 1)(b 2)(c 3))。我想要但不能產生的附加結果是在兩個給出的參數列表長度不相同的情況下,所以我想要的結果是(zip'(abc)'(1))=>(( a 1)(b())(c()))如果第一個列表中沒有要映射到第二個列表的項目,它只與一個空列表配對,但與當前函數定義不起作用。 – Yoink