首页 > 解决方案 > 如何在方案中使用 foldr 编写解压缩?

问题描述

这是unzip在 Scheme 中编码的函数的代码

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

会给我们这样的输出:

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

但我很好奇如何unzip使用 Schemefoldr函数实现相同的功能,任何人都可以帮忙吗?真的提前谢谢了。

标签: recursionfunctional-programmingschemeracket

解决方案


由于您使用了racket标签,我将使用 给出答案,它的语法比orfor/fold好得多。1foldrfoldl

for 的语法for/fold大致是:

(for/fold <accumulators>
          <iterators>
  <body>)

我们可以使用两个累加器ret1ret2存储两个列表中的每一个,然后将它们放在累加器#:result形式中:

([ret1 '()]
 [ret2 '()]
 #:result (list (reverse ret1) (reverse ret2)))

迭代器相当简单:

 ([i (in-list lst)])

最后,body 只需要拆分每一对,并将其附加到累加器中:

(values (cons (car i) ret1)
        (cons (cdr i) ret2))

所以把它们放在一起给出:

(define (unzip lst)
  (for/fold ([ret1 '()]
             [ret2 '()]
             #:result (list (reverse ret1) (reverse ret2)))
            ([i (in-list lst)])
    (values (cons (car i) ret1)
            (cons (cdr i) ret2))))

正如预期的那样:

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

1至少在我看来,这些事情总是有点主观。


推荐阅读