如何在Racket中按元素的car部分对cons单元列表排序?
解决按cons单元car部分排序原列表的问题
我懂你的困扰啦——你已经把原列表里所有cons单元的car数字单独抽出来排好序了,但现在卡壳在怎么把这些排序后的数字和原列表里对应的(数字+单词)cons单元重新对应起来,对吧?
其实你不用绕先排数字再匹配的弯路,直接对原列表的cons单元排序就好,这样能全程保留数字和单词的关联,比拆分开再匹配要简单得多。
推荐方案:直接用sort函数配合自定义比较规则
Scheme/Racket里的sort函数支持传入一个自定义的比较函数,你可以直接让它根据每个cons单元的car部分来排序:
(define (sort-by-car-number lst) ; 对原列表排序,比较规则是两个cons单元的car部分谁更大(降序) (sort lst (lambda (pair1 pair2) (> (car pair1) (car pair2)))))
举个实际例子,假设你的原列表是:
'((5 . "apple") (2 . "banana") (7 . "cherry") (3 . "date"))
调用(sort-by-car-number 原列表)后,会得到按car数字降序排列的结果:
'((7 . "cherry") (5 . "apple") (3 . "date") (2 . "banana"))
如果想要升序排列,只需要把比较函数里的>换成<就行。
如果你坚持要用已排序的数字列表来匹配(不推荐)
要是你一定要基于已经排好的number-list来做,也可以通过遍历数字列表,在原列表里找到对应car的cons单元,但要注意如果原列表有重复数字的car,这个方法会丢失重复项(因为find只会返回第一个匹配的元素):
(define (sort-by-car-number lst) (let ((number-list (sort (map car lst) >))) (map (lambda (num) ; 在原列表中找到car等于当前数字的cons单元 (find (lambda (pair) (= (car pair) num)) lst)) number-list)))
比如原列表如果是'((5 . "apple") (5 . "apricot") (2 . "banana")),这个方法只会返回'((5 . "apple") (5 . "apple") (2 . "banana")),丢失了第二个(5 . "apricot"),所以这种方法不如直接排序原列表靠谱。
总的来说,直接对原列表使用带自定义比较函数的sort是最简洁、最不容易出错的方案~
内容的提问来源于stack exchange,提问作者user9736725
相关产品推荐
相关产品推荐

