CLIPS语言sort函数对含ё俄语单词排序错误的解决咨询
解决CLIPS中俄语字符串排序的ё字母位置问题
在使用CLIPS语言的sort函数结合自定义string>函数排序俄语单词列表时,出现了不符合俄语字母表顺序的问题——单词ёжик被排到了列表末尾,而按照俄语字母表,ё是第7个字母,应该紧跟在еда之后。
原实现代码
(deffunction string> (?a ?b) (> (str-compare ?a ?b) 0) ) (defrule main => (bind ?list (create$ гора цапля дом еда ёжик игра соль йод кошка лось мост ворона номер арбуз опера пульс радуга тополь урок флот ходули шуба банан щука ь чаша ы ъ экран юрта зима якорь жизнь)) (printout t "original list: " ?list crlf) (bind ?list (sort string> ?list)) (printout t "sorted list: " ?list crlf) ) (reset) (run) (exit)
错误输出结果
~/dst/clips/clips_core_source/clips_core_source_642/clips_642 -f2 sort-small.bat original list: (гора цапля дом еда ёжик игра соль йод кошка лось мост ворона номер арбуз опера пульс радуга тополь урок флот ходули шуба банан щука ь чаша ы ъ экран юрта зима якорь жизнь) sorted list: (арбуз банан ворона гора дом еда жизнь зима игра йод кошка лось мост номер опера пульс радуга соль тополь урок флот ходули цапля чаша шуба щука ъ ы ь экран юрта якорь ёжик)
正确预期排序结果
sorted list: (арбуз банан ворона гора дом еда ёжик жизнь зима игра йод кошка лось мост номер опера пульс радуга соль тополь урок флот ходули цапля чаша шуба щука ъ ы ь экран юрта якорь) ; ^^^^
问题原因
CLIPS内置的str-compare函数是基于系统默认字符编码(通常是UTF-8)的数值进行比较,而ё在UTF-8中的编码值远高于大部分俄语字母,因此会被排到列表末尾,无法遵循俄语字母表的实际顺序。
解决方案
需要自定义基于俄语字母表顺序的比较逻辑:
- 定义完整的俄语字母顺序映射,给每个字母分配对应的优先级数值;
- 编写辅助函数获取单个字符的优先级;
- 重写
string>函数,通过逐个字符比较优先级来判断字符串的大小关系。
修改后的完整代码
; 定义俄语字母的优先级顺序,按字母表顺序排列 (deffunction char-weight (?c) (bind ?alphabet (create$ а б в г д е ё ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я)) (bind ?index (member$ ?c ?alphabet)) (if ?index then (nth$ ?index (create$ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33)) else 999) ) ; 自定义字符串比较函数,基于俄语字母优先级 (deffunction string> (?a ?b) (bind ?len-a (str-length ?a)) (bind ?len-b (str-length ?b)) (bind ?min-len (min ?len-a ?len-b)) (loop-for-count (?i 1 ?min-len) do (bind ?char-a (sub-string ?i ?i ?a)) (bind ?char-b (sub-string ?i ?i ?b)) (bind ?w-a (char-weight ?char-a)) (bind ?w-b (char-weight ?char-b)) (if (> ?w-a ?w-b) then (return TRUE)) (if (< ?w-a ?w-b) then (return FALSE)) ) ; 前面字符都相同,长度更长的字符串更大 (> ?len-a ?len-b) ) (defrule main => (bind ?list (create$ гора цапля дом еда ёжик игра соль йод кошка лось мост ворона номер арбуз опера пульс радуга тополь урок флот ходули шуба банан щука ь чаша ы ъ экран юрта зима якорь жизнь)) (printout t "original list: " ?list crlf) (bind ?list (sort string> ?list)) (printout t "sorted list: " ?list crlf) ) (reset) (run) (exit)
代码说明
char-weight函数:将输入的俄语字符映射为对应的优先级数字,未在字母表中的字符会被分配较高优先级(999),确保排在末尾;string>函数:逐个比较两个字符串的字符优先级,若某一位置的字符优先级更高,则返回TRUE;若前面所有字符都相同,则长度更长的字符串视为更大;- 运行修改后的代码,
ёжик会按照俄语字母表顺序,紧跟在еда之后,得到预期的排序结果。
内容的提问来源于stack exchange,提问作者Sergey Piskunov
相关产品推荐
相关产品推荐

