我试图找到一种方法将列表分成三部分。我使用了一个辅助函数,参数应该如下:它评估为三个列表的列表,包含1)列表中的项目少于枢轴,2)列表中的项目等于枢轴,3)列表中的项目大于pivot。
(define (partition lst item)
(define (partition-iter lst less same greater)
(cond ((null? lst)(list less same greater ))
((< (car lst) item)(partition-iter (cdr lst)
(cons (car lst) less)
same
greater ))
((= (car lst) item)
less
(cons (car lst) same)
(else
(partition-iter (cdr lst) (cons (car lst) greater))))))
(partition-iter lst '() '() '()))
除了else子句之外的所有内容都应该可以工作但是之后我就卡住了。任何帮助表示赞赏
答案 0 :(得分:1)
当前辅助函数partition-iter
由于其设计中的一些严重错误而无法工作。但首先,让我提供两个有用的版本:
第一个(简单)版本,
#lang racket
; LoN = List-of-Numbers
; partition :: LoN Number -> List-of-LoN
(define (partition1 lst pivot)
(local([; auxiliary function
; part :: LoN LoN LoN LoN -> List-of-LoN
define (part xs LT EQ GT)
; if empty list
(if (null? xs) (list LT EQ GT)
;else
(let* ([head (first xs)]
[tail (rest xs)]
[prtd (part tail LT EQ GT)]
[LT* (first prtd)]
[EQ* (second prtd)]
[GT* (third prtd)])
;--in--
(cond
; if x < pivot, add the element to LT
[(< head pivot) (list {cons head LT*} EQ* GT*)]
; if x = pivot, add the element to EQ
[(= head pivot) (list LT* {cons head EQ*} GT*)]
; if x > pivot, add the element to GT
[else (list LT* EQ* {cons head GT*})]
)
) ) ]
)
;--in--
(part lst null null null)
)
)
第二个版本,更接近您的实施,但使用fold
:
#lang racket
; partition :: LoN Number -> List-of-LoN
(define (partition2 lst pivot)
(local([; auxiliary function
; part :: LoN LoN LoN LoN -> List-of-LoN
define (part x LT-EQ-GT)
(local ([define-values (LT* EQ* GT*) (apply values LT-EQ-GT)])
;--in--
(cond
; if x < pivot, add the element to LT
[(< x pivot) (list {cons x LT*} EQ* GT*)]
; if x = pivot, add the element to EQ
[(= x pivot) (list LT* {cons x EQ*} GT*)]
; if x > pivot, add the element to GT
[else (list LT* EQ* {cons x GT*})]
)
) ]
)
;--in--
(foldr part '(() () ()) lst)
)
)
尝试例如,
(partition2 '(1 2 3 4 4 3 4 5 6) 4) ;; yields '((1 2 3 3) (4 4 4) (5 6)).
请注意,第二个(fold
- )版本更快(并且更好)。
最后,您的实现在以下行中出错(行号从1开始):
- 第4-7行应该是:
(partition-iter (cdr lst) (cons (car lst) less) same greater)
- 第9-10行应该是:
(partition-iter (cdr lst) less (cons (car lst) same) greater)
- 第12行应该是:
(partition-iter (cdr lst) less same (cons (car lst) greater))
最后,根据您当前的实施情况,您应该在最后一行使用foldl
或foldr
(或类似内容)。
答案 1 :(得分:0)
这里是您的代码,缩进以便相应的项目在视觉上对齐:
(define (partition lst item)
(define (partition-iter lst less same greater)
(cond
((null? lst)
(list less same greater ))
((< (car lst) item)
(partition-iter (cdr lst)
(cons (car lst) less)
same
greater))
((= (car lst) item)
less
(cons (car lst) same)
(else
(partition-iter (cdr lst)
(cons (car lst) greater))))))
(partition-iter lst '() '() '()))
我认为您可以立即看到它出现问题,现在。它是不对称的,所有这些都是出于怪癖,即使parens是平衡的。一个else
子句里面另一个cond
子句?什么是那个??
道德是,不要害怕使用白色空间来更好地看待。有很多很多空白区域。
没有它,Scheme往往看起来像一个难以理解的文字墙,parens或没有parens。和推荐的缩进风格。请问。不。救命。修复是显而易见的,简单的,简单的:只需以相同的样式完成代码你(??)开始编写它。处理其他两种情况,在输入列表中迭代时构建三个临时列表,在三种情况下重复cdr
次:
(define (partition lst item)
(define (partition-iter lst less same greater)
(cond
((null? lst)
(list less same greater ))
((< (car lst) item)
(partition-iter (cdr lst)
(cons (car lst) less)
same
greater ))
((= (car lst) item)
(partition-iter (cdr lst)
less
(cons (car lst) same)
greater ))
(else ; (> (car lst) item) ; keep it here for documentation!
(partition-iter (cdr lst)
less
same
(cons (car lst) greater) )) ))
(partition-iter lst '() '() '()))
我现在甚至不必将它装入DrRacket以确保它没问题。
对称很漂亮。对称是对的。
BTW,在带有警卫的模式匹配伪代码中,它可以写成partition lst item = partition-iter lst [] [] []
where
partition-iter [] less same greater = [less, same, greater]
partition-iter [a, ...lst] less same greater
| a < item = partition-iter lst [a, ...less] same greater
| a == item = partition-iter lst less [a, ...same] greater
| else = partition-iter lst less same [a, ...greater]
我觉得这在视觉上更明显。在它与正确的Scheme之间来回走动是一个纯粹的语法转换问题。