在Racket中比较简单列表与含多子列表的列表,获取匹配度最高的两个子列表
解决Racket中列表匹配度最高的两个子列表问题
首先得先指出你代码里的一个关键小问题:你定义db和indata时用了双重引号('('green ...)),这会导致每个元素变成带quote的特殊符号(比如'green本身是一个符号,而非你实际想要的green),后续匹配时根本找不到相同元素!先把定义修正过来:
;; 修正后的数据库列表,每个子列表直接用单引号定义元素 (define db (list '(green blue yellow orang) '(black blue darkblue white) '(brown red turkos pink))) ;; 修正后的待匹配简单列表 (define indata '(green blue))
接下来我们一步步实现匹配逻辑:
1. 编写匹配数计算函数
首先需要一个辅助函数,计算待匹配列表和某个子列表的匹配元素数量——也就是两个列表的交集大小:
(define (match-count target sublst) ;; 统计target中在sublst里出现的元素个数 (length (filter (lambda (elem) (member elem sublst)) target)))
测试一下这个函数:(match-count indata (first db))会返回2(green和blue都匹配);(match-count indata (second db))返回1(仅blue匹配),完全符合预期。
2. 给子列表排序并筛选前两名
接下来我们要把数据库里的每个子列表和对应的匹配数绑定,然后按匹配数从高到低排序,最后取出前两个子列表:
完整的compare函数实现如下:
(define (compare lst database) ;; 内部辅助函数:计算匹配元素数量 (define (match-count target sublst) (length (filter (lambda (elem) (member elem sublst)) target))) ;; 生成「匹配数-子列表」的配对列表,并按匹配数降序排序 (define sorted-pairs (sort (map (lambda (sublst) (list (match-count lst sublst) sublst)) database) (lambda (pair-a pair-b) (> (car pair-a) (car pair-b))))) ;; 处理边界情况:如果数据库子列表不足2个,直接返回所有;否则返回前两个 (if (>= (length sorted-pairs) 2) (list (cadr (first sorted-pairs)) (cadr (second sorted-pairs))) (map cadr sorted-pairs)))
测试验证
调用(compare indata db),会返回:
'((green blue yellow orang) (black blue darkblue white))
完全符合预期:第一个子列表匹配2个元素,第二个匹配1个,是匹配度最高的两个。
如果你的数据库里有多个匹配数相同的子列表,这个函数会保留它们在原数据库中的相对顺序(Racket的sort默认是不稳定排序,若需要严格稳定排序,可以调整比较逻辑,不过一般场景下当前实现足够使用)。
内容的提问来源于stack exchange,提问作者user9736725
相关产品推荐
相关产品推荐

