在我正在使用 Racket 处理的应用程序中,我需要获取一个数字列表并将该列表划分为连续数字的子列表:(在实际应用程序中,我实际上将划分由数字和一些数据组成的对,但原理是一样的。)
即如果我的程序被调用chunkify
,那么:
(chunkify '(1 2 3 5 6 7 9 10 11)) -> '((1 2 3) (5 6 7) (9 10 11))
(chunkify '(1 2 3)) -> '((1 2 3))
(chunkify '(1 3 4 5 7 9 10 11 13)) -> '((1) (3 4 5) (7) (9 10 11) (13))
(chunkify '(1)) -> '((1))
(chunkify '()) -> '(())
等等
我在 Racket 中提出了以下内容:
#lang racket
(define (chunkify lst)
(call-with-values
(lambda ()
(for/fold ([chunk '()] [tail '()]) ([cell (reverse lst)])
(cond
[(empty? chunk) (values (cons cell chunk) tail)]
[(equal? (add1 cell) (first chunk)) (values (cons cell chunk) tail)]
[else (values (list cell) (cons chunk tail))])))
cons))
这工作得很好,但我想知道如果没有更直接更简单的方法来做到这一点,那么我想知道 Racket 的表现力,某种方式来摆脱“带值调用”和需要反转列表在程序等方面,也许有些完全不同。
我的第一次尝试非常松散地基于“The Little Schemer”中的收集器模式,这比上面的更简单:
(define (chunkify-list lst)
(define (lambda-to-chunkify-list chunk) (list chunk))
(let chunkify1 ([list-of-chunks '()]
[lst lst]
[collector lambda-to-chunkify-list])
(cond
[(empty? (rest lst)) (append list-of-chunks (collector (list (first lst))))]
[(equal? (add1 (first lst)) (second lst))
(chunkify1 list-of-chunks (rest lst)
(lambda (chunk) (collector (cons (first lst) chunk))))]
[else
(chunkify1 (append list-of-chunks
(collector (list (first lst)))) (rest lst) list)])))
我正在寻找的是简单,简洁和直接的东西。