Scheme 逆向列表函数

Scheme Inverse List Function

我定义了一个名为 zip 的函数,它以两个列表作为参数并返回一个对列表。

(define (zip list1 list2)
(if (null? list1)
  '()
   (cons (list (cons (car list1) (car list2)))
            (zip (cdr list1) (cdr list2)))))

(zip (list 1 3 5) (list 2 4 6))
> (((1 . 2)) ((3 . 4)) ((5 . 6)))

现在我基本上无法编写它的反函数。这是我到目前为止所拥有的。该函数需要输出两个列表的列表。我只是尝试制作两个列表中的第一个以使自己更容易,但输出不是我想要的。

(define (unzip u-list)
  (if (null? u-list)
      '()
       (list (car (car (car u-list))) (unzip(cdr u-list)))))


(unzip (zip (list 1 3 5) (list 2 4 6)))
> (1 (3 (5 ())))

任何帮助将不胜感激...

我认为您的 zip 实现存在问题,您是否注意到您返回的是单元素对列表?返回成对列表更有意义:

(define (zip lst1 lst2)
  (if (null? lst1)
      '()
      (cons (cons (car lst1) (car lst2))
            (zip (cdr lst1) (cdr lst2)))))

或者更好的是,让我们使用 map 高阶函数来获得更短、更惯用的解决方案:

(define (zip lst1 lst2)
  (map cons lst1 lst2))

关于 unzip:如果我们将问题分成几部分会更容易 - 让我们获取每对的第一个元素,然后是每对的第二个元素,最后构建一个包含答案的列表。试试这个:

(define (unzip lst)
  (define (firsts lst)
    (if (null? lst)
        '()
        (cons (caar lst)
              (firsts (cdr lst)))))
  (define (seconds lst)
    (if (null? lst)
        '()
        (cons (cdar lst)
              (seconds (cdr lst)))))
  (list (firsts lst) (seconds lst)))

但是,我们又一次在重新发明轮子。让我们使用内置函数来写一个更简单的答案:

(define (unzip lst)
  (list (map car lst) (map cdr lst)))

无论如何,现在 unzipzip 的倒数:

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

(unzip '((1 . 2) (3 . 4) (5 . 6)))
=> '((1 3 5) (2 4 6))

当你成对制作时,它会更难一些,但并不多:

(define (zip-pair a b)
  (map cons a b))

(define (unzip-pair zipped-pair)
  (list (map car zipped-pair) 
        (map cdr zipped-pair)))

zipusually implementedapplymap 并获取列表并生成列表列表,如下所示:

(define (zip . lists)
  (apply map list lists))

(zip '(1 2 3) '(a b c)) ; ==> ((1 a) (2 b) (3 c))

虽然这会列出列表而不是配对。然而,解压缩几乎是相同的,除了你将采用列表列表而不是可变数量的参数:

(define (unzip1 zipped-list)
  (apply map list zipped-list))

; or reuse zip
(define (unzip1 zipped-list)
  (apply zip zipped-list))

(unzip1 '((1 a) (2 b) (3 c))) ; ==> ((1 2 3) (a b c))