(define unzip (lambda (l)
(define front (lambda (a)
(if (null? a)
'()
(cons (car (car a)) (unzip (cdr a)))
)))
(define back (lambda (b)
(if (null? b)
'()
(cons (car (cdr (car b))) (unzip (cdr b)))
)))
(list (front l) (back l))))
(解压'((1 2)(3 4)(5 6)))
这个电话应该返回((1 3 5)(2 4 6)) 如果我用(前面l)或(后面l)替换最后一行代码“(list(前面l)(后面l))我得到正确的列表但我似乎无法将它们放在一起它只是不断吐出每次尝试都会产生奇怪的输出。
答案 0 :(得分:2)
你的代码结构非常传统,我怀疑你是计划/球拍的新手。您的程序可以用更加惯用的方式编写。
我可能对您的代码提出的第一个批评是,它假设您解压缩的列表每个只有2个元素。
这些问题都指向一个有助于塑造结构良好程序的基本概念:
"什么是"总计"程序?"
总程序是为所接受类型的所有值定义的程序。这对我们意味着,如果我们编写unzip
程序,它应该
让我们来看一下现在这样做的unzip
程序。这个程序可能会得到改善,但至少,它易于理解和理解
(define (unzip xs (ys empty))
; if no xs are given, return ys
(cond [(empty? xs) empty]
; if the first input is empty, return the final answer; reversed
[(empty? (car xs)) (reverse ys)]
; otherwise, unzip the tail of each xs, and attach each head to ys
[else (unzip (map cdr xs) (cons (map car xs) ys))]))
(unzip '((1 2) (3 4) (5 6)))
; => '((1 3 5) (2 4 6))
让我们逐步完成评估。
; initial call
(unzip '((1 2) (3 4) (5 6)))
; (empty? xs) nope
; (empty? (car xs)) nope
; (unzip (map cdr xs) (cons (map car xs) ys))
; substitue values
(unzip (map cdr '((1 2) (3 4) (5 6)))
(cons (map car '((1 2) (3 4) (5 6))) empty))
; eval (map cdr xs)
(unzip '((2) (4) (6))
(cons (map car '((1 2) (3 4) (5 6))) empty))
; eval (map car xs)
(unzip '((2) (4) (6))
(cons '(1 3 5) empty))
; eval cons
; then recurse unzip
(unzip '((2) (4) (6))
'((1 3 5)))
; (empty? xs) nope
; (empty? (car xs)) nope
; (unzip (map cdr xs) (cons (map car xs) ys))
; substitue values
(unzip (map cdr '((2) (4) (6)))
(cons (map car '((2) (4) (6))) '((1 3 5))))
; eval (map cdr xs)
(unzip '(() () ())
(cons (map car '((2) (4) (6))) '((1 3 5))))
; eval (map car xs)
(unzip '(() () ())
(cons '(2 4 5) '((1 3 5))))
; eval cons
; then recurse
(unzip '(() () ())
'((2 4 5) (1 3 5)))
; (empty? xs) nope
; (empty? (car xs)) yup!
; (reverse ys)
; substituion
(reverse '((2 4 5) (1 3 5)))
; return
'((1 3 5) (2 4 5))
这是另一件值得思考的事情。您是否注意到unzip
基本上与zip
做同样的事情?让我们仔细看看你的输入
'((1 2)
(3 4)
(5 6))
^ ^
查看列。如果我们要zip
这些,我们就会
'((1 3 5) (2 4 6))
"等等,你是说unzip
只是另一个zip
,反之亦然?"
烨。
(unzip '((1 2) (3 4) (5 6)))
; => '((1 3 5) (2 4 6))
(unzip (unzip '((1 2) (3 4) (5 6))))
; '((1 2) (3 4) (5 6))
(unzip (unzip (unzip '((1 2) (3 4) (5 6)))))
; '((1 3 5) (2 4 6))
了解这一点,如果您已经有zip
程序,那么您对unzip
的定义就变得非常简单
(define unzip zip)
这基本上意味着:
您不需要unzip
程序,只需重新zip
(zip '((1 2) (3 4) (5 6)))
; => '((1 3 5) (2 4 6))
(zip (zip '((1 2) (3 4) (5 6))))
; '((1 2) (3 4) (5 6))
(zip (zip (zip '((1 2) (3 4) (5 6)))))
; '((1 3 5) (2 4 6))
无论如何,我猜测你的unzip
程序实现是一个功课。你教授期待的长期答案可能与我最初提供的程序有关。偷偷摸摸的答案是(define unzip zip)
"这个unzip
程序是否也被视为完整程序?"
如何解压缩3个5个元素的列表或5个3个元素的列表?
(unzip '((a b c d e) (f g h i j) (k l m n o p)))
; => '((a f k) (b g l) (c h m) (d i n) (e j o))
(unzip '((a b c) (d e f) (g h i) (k l m) (n o p)))
; => '((a d g k n) (b e h l o) (c f i m p))
如何解压缩4个4个元素的列表?
(unzip '((a b c d) (e f g h) (i j k l) (m n o p)))
; => '((a e i m) (b f j n) (c g k o) (d h l p))
如何解压缩1个7个元素的列表或7个1个元素的列表?
(unzip '((a b c d e f g)))
; => '((a) (b) (c) (d) (e) (f) (g))
(unzip '((a) (b) (c) (d) (e) (f) (g)))
; => '((a b c d e f g))
怎么样解压缩?
(unzip '())
; => '()
如何解压缩3个空列表?
(unzip '(() () ()))
; => '()
1 我们说
unzip
应该"接受任何长度的列表"但是我们在这里稍微弯曲规则。unzip
接受任何长度的列表都是正确的,但每个列表的长度与其他列表的长度相同也是正确的。对于不同长度的列表,目标"正确"解决方案是不可能的,在本课程中,我们将混合长度列表的行为保留为 undefined 。; mixed length input is undefined (unzip '((a) (b c d) (e f))) ; => ???
附注:
像
这样的事情(car (car x))
(car (cdr (car x)))
可以简化为
(caar x)
(cadar x)
以下pair accessor short-hand procedures存在
caar ; (car (car x))
cadr ; (car (cdr x))
cdar ; (cdr (car x))
cddr ; (cdr (cdr x))
caaar ; (car (car (car x)))
caadr ; (car (car (cdr x)))
cadar ; (car (cdr (car x)))
caddr ; (car (cdr (cdr x)))
cdaar ; (cdr (car (car x)))
cdadr ; (cdr (car (cdr x)))
cddar ; (cdr (cdr (car x)))
cdddr ; (cdr (cdr (cdr x)))
caaaar ; (car (car (car (car x))))
caaadr ; (car (car (car (cdr x))))
caadar ; (car (car (cdr (car x))))
caaddr ; (car (car (cdr (cdr x))))
cadaar ; (car (cdr (car (car x))))
cadadr ; (car (cdr (car (cdr x))))
caddar ; (car (cdr (cdr (car x))))
cadddr ; (car (cdr (cdr (cdr x))))
cdaaar ; (cdr (car (car (car x))))
cdaadr ; (cdr (car (car (cdr x))))
cdadar ; (cdr (car (cdr (car x))))
cdaddr ; (cdr (car (cdr (cdr x))))
cddaar ; (cdr (cdr (car (car x))))
cddadr ; (cdr (cdr (car (cdr x))))
cdddar ; (cdr (cdr (cdr (car x))))
cddddr ; (cdr (cdr (cdr (cdr x))))
答案 1 :(得分:0)
它正确地组合了列表,但它没有组合正确的列表。
提取本地定义使它们可以单独测试:
(define (front a)
(if (null? a)
'()
(cons (car (car a)) (unzip (cdr a)))))
(define (back b)
(if (null? b)
'()
(cons (car (cdr (car b))) (unzip (cdr b)))))
(define (unzip l)
(list (front l) (back l)))
(define test '((1 2) (3 4) (5 6)))
测试:
> (front test)
'(1 (3 (5 () ()) (6 () ())) (4 (5 () ()) (6 () ())))
> (front '((1 2)))
'(1 () ())
> (back '((1 2)))
'(2 () ())
...怪异
> (unzip '())
'(() ())
> (unzip '((1 2)))
'((1 () ()) (2 () ()))
看起来某事是正确的,但是列表'尾巴是错的。
如果仔细查看front
和back
的定义,他们会重新加入unzip
。
但他们应该回归自己 - front
是第一个"第一个"其次是"第一"其余的,back
是"第一秒"其次是"秒"
unzip
与此无关。
(define (front a)
(if (null? a)
'()
(cons (car (car a)) (front (cdr a)))))
(define (back b)
(if (null? b)
'()
(cons (car (cdr (car b))) (back (cdr b)))))
现在......
> (front test)
'(1 3 5)
> (back test)
'(2 4 6)
> (unzip test)
'((1 3 5) (2 4 6))