如何在 Scheme 中将列表分成两部分

How to split a list into two parts in Scheme

示例:(split '(1 2 3 4) '3)

答案应该是:((1 2 3) 4)

函数需要1个列表和1个数字,输出应该是嵌套列表 嵌套列表由 "mylist" 中等于或小于 "num" 的所有元素组成,较大的数字应位于列表右侧。

我试过了,但输出的只是一个列表:

(define (split mylist num)
  (cond
    ((null? mylist)'())
    ((list? (car mylist))(split(car mylist) num))
    ((> (car mylist) num)(split(cdr mylist) num))
    (else(cons (car mylist) (split(cdr mylist) num)))))

一个简单的解决方案:

(define (split-list xs y) 
  (define (less x)    (<= x y))
  (define (greater x) (>  x y))
  (list (filter less xs)
        (filter greater xs)))

备选方案:

(define (split-list xs y) 
  (define (less x) (<= x y))
  (define-values (as bs) (partition less xs))
  (list as bs))

(split-list '(1 2 3 4) 3)

这是一种可能的解决方案,使用 Racket 中的内置程序:

(define (split mylist num)
  (cons
   (takef mylist (lambda (n) (<= n num)))
   (dropf mylist (lambda (n) (<= n num)))))

例如:

(split '(1 2 3 4) 3)
=> '((1 2 3) 4)

(split '(1 2 3 4 5) 3)
=> '((1 2 3) 4 5)

这是使用命名 let 滚动您自己的版本。它使一次通过数据,结果是相反的顺序,因为它是最有效的。

(define (binary-bucket-sort lst threshold)
  (let loop ((lst lst) (less-equal '()) (greater '()))    
    (cond ((null? lst) 
           (cons less-equal greater))
          ((<= (car lst) threshold) 
           (loop (cdr lst) (cons (car lst) less-equal) greater))
          (else 
           (loop (cdr lst) less-equal (cons (car lst) greater))))))

(binary-bucket-sort '(1 5 9 2 6 10 3 7 9 8 4 0) 5) 
; ==> ((0 4 3 2 5 1) . (8 9 7 10 6 9))

如果您对 Racket 中的一些更实用的结构感到满意,例如 curry 等,您可以使用这种相当紧凑的方法:

(define (split-list xs y) 
  (call-with-values (thunk (partition (curry >= y) xs)) cons))

> (split-list '(1 2 3 4 5 6 7) 3)
'((1 2 3) 4 5 6 7)