按长度对列表列表进行排序

sort list of lists by length

我正在完成一个 Scheme 教程,该教程要求使用排序进行练习,“按列表的长度按降序排序。”我自己写了这个解决方案:

(define (ls-len-sort ls)
  (sort ls (lambda (x y) (> (length x) (length y)))))

但是当我测试它时,我并没有得到我期望的结果:

> (ls-len-sort '('(1) '(3 3 3) '(5 5 5 5 5) '(4 4 4 4) '(2 2)))
'('(1) '(3 3 3) '(5 5 5 5 5) '(4 4 4 4) '(2 2))

我预计 '('(5 5 5 5 5) '(4 4 4 4) '(3 3 3) '(2 2) '(1))

排序有效,比较列表长度有效。

> (sort '(1 3 5 4 2) >)
'(5 4 3 2 1)
> (sort '(1 3 5 4 2) (lambda (x y) (< (abs (sin x)) (abs (sin y)))))
'(3 4 1 2 5)
> (> (length '(2 2)) (length '(3 3 3)))
#f
> (> (length '(4 4 4 4)) (length '(3 3 3)))
#t

但是对元素为列表的列表进行排序不会:

> (sort '('(1) '(3 3 3) '(5 5 5 5 5) '(4 4 4 4) '(2 2)) (lambda (x y) (> (length x) (length y))))
'('(1) '(3 3 3) '(5 5 5 5 5) '(4 4 4 4) '(2 2))

我在教程里查了正确答案,和我写的一样,一模一样:

(define (sort-length ls)
  (sort ls (lambda (x y) (> (length x) (length y)))))

所以我猜这可能是 Racket v8.4 [cs] 与本教程所针对的 MIT-Scheme (R5RS) 版本之间的区别?

你得到这个结果是因为 quote. Quote isn't just different name for function list 的错误使用,它是不评估其参数和 returns 的形式。比较这两个例子:

> (list 1 2 3 (+ 2 2) 5)
(1 2 3 4 5)

> '(1 2 3 (+ 2 2) 5)
(1 2 3 (+ 2 2) 5)

有时结果是一样的:

> (list 1 2 3 4 5)
(1 2 3 4 5)

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

当一个列表被引用时,里面的所有对象也被引用,所以你不必引用它们两次。如您所见,结果完全不同:

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

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

您想要哪种变体?您可以将这两个与使用 list:

创建的列表进行比较
> (list (list 1) (list 3 3 3) (list 5 5 5 5 5) (list 4 4 4 4) (list 2 2))
((1) (3 3 3) (5 5 5 5 5) (4 4 4 4) (2 2))

当您使用正确的变体时,sort 将起作用:

(define (ls-len-sort ls)
  (sort ls < #:key length))

> (ls-len-sort '((1) (3 3 3) (5 5 5 5 5) (4 4 4 4) (2 2)))
((1) (2 2) (3 3 3) (4 4 4 4) (5 5 5 5 5))