【问题标题】:Scheme Inverse List Function方案反向列表函数
【发布时间】:2016-01-16 07:14:57
【问题描述】:

我定义了一个名为 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)))

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

(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 ())))

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

【问题讨论】:

    标签: list recursion functional-programming scheme


    【解决方案1】:

    我认为您的 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))
    

    【讨论】:

    • 感谢您的帮助!这现在更有意义了。
    【解决方案2】:

    当你用成对制作时,它有点难,但并不多:

    (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))
    

    【讨论】:

    • 所以zip 是它自己的逆(几乎)。好的。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    • 2010-12-25
    相关资源
    最近更新 更多