【问题标题】:Sort a list in scheme对方案中的列表进行排序
【发布时间】:2013-05-28 17:16:21
【问题描述】:

我想创建对列表进行排序的函数。例如我有这个列表:

x1, x2, x3 .... xn

1, 2, 3, 4, 5, 6

我想按这个顺序显示数字:

x1, xn, x2, xn-1

1, 6, 2, 5, 3, 4

你能帮我写这个例子吗?

【问题讨论】:

    标签: scheme


    【解决方案1】:

    通常当我们谈论排序时,我们指的是根据项目内容的某些特征对项目进行排序,而不是项目在列表中的位置。我会称您的情况为置换,但也许有些人也会对这种用法提出异议。 :-)

    以下是解决问题的方法:

    1. 在中间拆分列表(如果您只想遍历列表一次,可以使用龟兔赛跑);如果您愿意,请调用这些列表 headtail
    2. 反转tail 列表,并将其与head 列表交错。

    另一种方法:

    1. 反转原始列表对(我们称之为rev)。
    2. 将原始列表与rev 交错,跟踪每次遍历的元素。当他们在中间相遇时,停下来。

    这是第二种方法的演示(需要加载SRFI 1):

    (define (zippy lst)
      (if (null? lst)
          '()
          (let recur ((lst lst)
                      (rev (pair-fold cons '() lst)))
            (cond ((eq? lst (car rev)) (list (car lst)))
                  ((eq? (cdr lst) (car rev)) (list (car lst) (caar rev)))
                  (else (cons* (car lst) (caar rev)
                               (recur (cdr lst) (cdr rev))))))))
    

    【讨论】:

    • ...和Óscar López的回答展示了第一种方法。 :-) +1
    【解决方案2】:

    这并不是真正的排序操作,更像是洗牌;这是解决它的另一种方法。首先,让我们定义interleave 过程,它从两个列表中交替元素,返回一个列表:

    (define (interleave l1 l2)
      (cond ((empty? l1) l2)
            ((empty? l2) l1)
            (else (cons (first l1)
                        (interleave l2 (rest l1))))))
    

    现在我们取原始列表和中间的split-at(这是一个特定于Racket的程序);最后,我们将两个结果列表交错,反转尾部:

    (define (zippy lst)
      (let-values (((head tail) (split-at lst (quotient (length lst) 2))))
        (interleave head (reverse tail))))
    

    以上实现恕我直言,更直观一点,如果您使用的是 Racket,它不需要外部库。它按预期工作:

    (zippy '(1 2 3 4 5 6))
    => '(1 6 2 5 3 4)
    

    【讨论】:

    • 非常好。 :-) 非 Racket 实现的注意事项:split-atSRFI 1 的一部分,let-valuesSRFI 11 的一部分。如果您的实现没有 SRFI 11,您也可以轻松地从 SRFI 8 转换为使用 receive,或者您可以直接使用 call-with-values,尽管后者更丑陋。 :-)
    • 顺便说一句,我认为(/ (length lst) 2) 为奇数长度的列表返回一个非整数,split-at 可能不喜欢。 (quotient (length lst) 2) 可能会更好。
    • @ChrisJester-Young 你当然是对的。已修复,谢谢!
    • 我发现了一个问题。如果我有这个顺序,我如何对数字进行排序:4, 2, 9, 3, 5, 1我如何对它们进行排序?
    • 您在问题中定义的顺序似乎取决于元素的位置,而不是它们的值。如果值相关,则在将列表提供给我的函数之前先对列表进行排序,使用sort 过程
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-17
    • 2018-03-11
    • 1970-01-01
    • 2016-04-21
    • 2018-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多