You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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中的编码值远高于大部分俄语字母,因此会被排到列表末尾,无法遵循俄语字母表的实际顺序。

解决方案

需要自定义基于俄语字母表顺序的比较逻辑:

  1. 定义完整的俄语字母顺序映射,给每个字母分配对应的优先级数值;
  2. 编写辅助函数获取单个字符的优先级;
  3. 重写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 13:34:51