我正在编写一个简单的全文搜索库,需要进行大小写折叠以检查两个单词是否相等。对于此用例,现有的.to_lowercase()
和.to_uppercase()
方法为not enough。
通过快速搜索crates.io,我可以找到用于规范化和分词的库,但不能找到案例折叠。 regex-syntax
确实有case folding code,但它的API中没有公开。
如果没有任何现有的解决方案,那么我可能不得不自己动手
答案 0 :(得分:2)
unicase crate没有直接公开case折叠,但它提供了一个通用的包装器类型,在不区分大小写的情况下实现Eq
,Ord
和Hash
方式。主分支(未发布)支持ASCII大小写折叠(作为优化)和Unicode大小写折叠(尽管只支持不变的大小写折叠)。
答案 1 :(得分:1)
对于我的用例,我发现caseless箱子最有用。
据我所知,这是唯一支持规范化的库。当您需要时,这很重要,例如“㎒”(U + 3392 SQUARE MHZ)和“mhz”匹配。有关其工作原理的详细信息,请参阅Unicode标准中的Chapter 3 - Default Caseless Matching。
以下是一些匹配字符串不区分大小写的示例代码:
extern crate caseless;
use caseless::Caseless;
let a = "100 ㎒";
let b = "100 mhz";
// These strings don't match with just case folding,
// but do match after compatibility (NFKD) normalization
assert!(!caseless::default_caseless_match_str(a, b));
assert!(caseless::compatibility_caseless_match_str(a, b));
要直接获取案例折叠字符串,您可以使用default_case_fold_str
函数:
let s = "Twilight Sparkle ちゃん";
assert_eq!(caseless::default_case_fold_str(s), "twilight sparkle ちゃん");
Caseless也没有公开规范化的相应函数,但你可以使用unicode-normalization crate写一个:
extern crate unicode_normalization;
use caseless::Caseless;
use unicode_normalization::UnicodeNormalization;
fn compatibility_case_fold(s: &str) -> String {
s.nfd().default_case_fold().nfkd().default_case_fold().nfkd().collect()
}
let a = "100 ㎒";
assert_eq!(compatibility_case_fold(a), "100 mhz");
请注意,需要多轮标准化和案例折叠才能获得正确的结果。
(感谢BurntSushi5指点我这个库。)