【问题标题】:zip function in Racket/SchemeRacket/Scheme 中的 zip 功能
【发布时间】:2014-03-08 11:27:02
【问题描述】:

给定两个列表,返回一个列表,其元素是大小为 2 的列表,这样对于 i-th 列表,第一个元素是第一个原始列表的 i-th 元素,并且第二个元素是第二个原始列表的i-th 元素。如果一个列表比另一个小,则结果列表的大小最小;因此,如果其中一个列表为空,则返回一个空列表。 例如:

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

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

【问题讨论】:

  • 到目前为止您尝试过什么?请张贴代码!否则人们会认为您想免费完成家庭作业;)

标签: recursion functional-programming scheme lisp racket


【解决方案1】:

如果您的map 实现在最短的列表中停止,则可以使用map、Scheme 的list 过程和apply 定义zip。这里有一个提示:

(define (zip . lsts)
  (apply <??> <??> lsts))

SRFI-1map 就足够了。所以在球拍中你添加(require (only-in srfi/1 map))

【讨论】:

    【解决方案2】:

    今天,我遇到了同样的练习并做了我自己的实现,这与这里发布的所有人都不同。所有其他答案都很棒。我真的很喜欢@Alinsoar 投票最多的那张。

    当然,其他答案实际上比我的实现要好。但无论如何我都会发布它。也许,这可以帮助尝试学习球拍的人。

    
    (define (shorter-list xs ys)
      (if (> (length xs) (length ys))
          ys
          xs))
    
    (define (zip xs ys)
      (cond [(null? (shorter-list xs ys)) null]
            [true (cons (list (car xs) (car ys)) (zip (cdr xs) (cdr ys)))]))
    
    

    【讨论】:

      【解决方案3】:

      如果我们接受 Racket 函数,并放宽返回 2 元组的要求,以支持更通用的 zip,那么我会检查 for/list。以下是压缩或交错两个或三个列表的示例,停在最短的列表

      (define l1 '(a b c))
      (define l2 '(1 2 3))
      (define l3 '(true false))
      
      ;; → '((a 1 true) (b 2 false))
      (for/list ([i l1] [j l2] [k l3])
                (list i j k))
      
      ;; → '((a 1) (b 2) (c 3))
      (for/list ([i l1] [j l2])
                (list i j))
      
      ;; → '()
      (for/list ([i l1] [j l2] [k null])
                (list i j k))
      

      【讨论】:

        【解决方案4】:

        试试看:

        (map cons '(1 2 3) '(a b c))
        

        左右:

        (map list '(1 2 3) '(a b c))
        

        (define zip (lambda (l1 l2) (map list l1 l2)))
        
        ->(zip '(1 2 3) '(x y z))
        '((1 x) (2 y) (3 z))
        

        【讨论】:

        • (map cons '(1 2 3) '(a b c)) ; ==&gt; ((1 . a) (2 . b) (3 . c)),不是想要的结果((1 a) (2 b) (3 c))
        • 那里可以使用任何函数,只要函数有2个输入参数。
        • 出于好奇,为什么zip 定义中的lambda?似乎(define (zip l1 l2) (map list l1 l2)) 也可以...?
        • 你写的是我写的语法糖。您写的表格在我在预处理期间写的内容中进行了扩展。但是在组合概念(o 运算符)或 section 概念下,Haskell 中存在更好的组合语法糖。在这种情况下,不需要显式传递参数的名称,因为 haskell 在预处理中会为您执行此操作。
        • 我不认为至少在 Racket 中做正确的事情 - 你只测试了输入长度相等的条件。此外,zip 通常也可以在流上工作,因此您可以使用(zip '(1 2 3) (in-naturals)) 创建一个索引对
        【解决方案5】:

        如果你已经解决了第一个元素的问题,那么你可以递归列表的其余部分:

        (define (zip l1 l2)
          (if (or (null? l1) (null? l2))
              '()
              (cons (list (car l1) (car l2))
                    (zip  (cdr l1) (cdr l2)))))
        

        如果您处理任一列表为空的基本情况。

        > (zip '(1 2 3 4) '(a b))
        ((1 a) (2 b))
        > (zip '() '(a b))
        ()
        

        【讨论】:

          【解决方案6】:

          因为你没有发布你写的代码,我猜这是作业。我会给你一些开始的提示,这是解决方案的一般结构,填空 - 如果你自己找到正确的答案会更有趣!

          (define (zip lst1 lst2)
            (cond ((<???> lst1)  ; if the first list is empty
                   <???>)        ; then return the empty list 
                  ((<???> lst2)  ; if the second list is empty
                   <???>)        ; then also return the empty list 
                  (else          ; otherwise
                   (cons (list   ; cons a list with two elements:
                          <???>  ; the first from the first list
                          <???>) ; and the first from the second list
                         (zip <???> <???>))))) ; advance recursion over both lists
          

          我用示例输入测试了上述实现,结果符合预期:

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

          【讨论】:

            猜你喜欢
            • 2012-10-24
            • 2018-11-10
            • 2017-06-03
            • 2017-03-30
            • 2019-05-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-03-21
            相关资源
            最近更新 更多