如何检查列表是否在Racket中排序?

时间:2014-03-24 13:42:39

标签: sorting scheme lisp racket

我正在尝试定义一个以列表作为参数的函数,并返回一个布尔值(#t或#f),指示列表是否按升序排序。函数的输出应该是这样的:

(sorted? '(1 2 3 4 5))             ; => #t
(sorted? '(1 2 5 6 4))             ; => #f
(sorted? '("frank" "adam" "eve"))  ; => #f
(sorted? '("adam" "eve" "frank"))  ; => #t

这是我尝试解决方案:

(define (sorted? lst)
  (cond
    [(< (length lst) 2]  
    [(<= (car lst) (cadr lst)) (sorted? (cdr lst))]
    [(string? lst) (string<=? (car lst) (cadr lst)) (sorted? (cdr lst))]
    [else #f]))

我不断收到关于字符串部分的错误,而我似乎无法弄清楚我做错了什么。我收到错误是因为我在同一个定义中有两种不同的类型吗?我只是假设,如果列表中的参数不符合条件,它就是条件语句,应该忽略它。我是新手,我需要帮助。如果您知道我做错了什么以及我需要做些什么来解决这个问题,请分享您的知识。感谢。

3 个答案:

答案 0 :(得分:1)

通常你不想混合数字和词汇排序,但想象一下你可以比较任何值:

(define (any<? a b)
  (cond ((and (number? a) (number? b)) (< a b))
        ((and (string? a) (string? b)) (string<? a b))
        ;; You can add types here. As a default we cast it 
        ;; to string and compare it as string
        ;; NB! format is Racket specific 
        (else (string<? (format "~A" a) (format "~A" b))))) 

所以让我们排序:

(define unsorted '(#\a  5 "hello" 9 (a c b) 10 (a b c) "50"))

;; NB: sort is racket specific, R6RS has list-sort 
;; with the arguments in reverse order.
(define sorted (sort test any<?)) 
test2 ; ==> ((a b c) (a c b) 5 "50" 9 10 #\a "hello")

;; Using a named let with the current element 
;; makes you only check null? once for each pair
(define (sorted? lst <)
  (or (null? lst)
      (let loop ((e (car lst)) (lst (cdr lst)))
        (or (null? lst)
            (and (not (< (car lst) e)) 
                 (loop (car lst) (cdr lst)))))))

(sorted? unsorted any<?) ; ==> #f
(sorted? sorted any<?)   ; ==> #t

如果您知道列表中元素的类型,则不会使用any<?但该数据的具体比较过程。例如。

(sorted? '("a" "b" "cd") string<?) ; ==> #t
(sorted? '(4 7 3 5 9 3 4 6) <)     ; ==> #f

答案 1 :(得分:0)

Scheme或Racket中没有适用于所有类型的通用<

您可以从如何定义Racket sort功能中获取提示。它不仅需要list?个参数。它还需要一个less-than?参数,它是一个函数(any/c any/c . -> . any/c),可以是<string<?或任何适合列表中事物类型的参数。

您的sorted?函数可以执行相同的操作 - 获取列表以及less-than?参数。

答案 2 :(得分:0)

正如其他人所说,您需要进行一次测试/比较&#39;比较你打算排序的任何函数。鉴于:

(define (sorted? test< list)
  (or (null? list)
      (null? (cdr list))
      (and (test< (car list) (cadr list))
           (sorted? test< (cdr list))))

这种功能看起来更好&#39;当您利用andor获取布尔结果时。

> (sorted? < '(0 1 2 3 0))
#f
> (sorted? < '(0 1 2 3 4))
#t
> (sorted? string<? '("a" "b" "c" "a"))
#f
> (sorted? char<? '(#\a #\b #\a))
#f
>