如何在Rust中折叠字符串?

时间:2016-10-25 22:49:14

标签: unicode rust

我正在编写一个简单的全文搜索库,需要进行大小写折叠以检查两个单词是否相等。对于此用例,现有的.to_lowercase().to_uppercase()方法为not enough

通过快速搜索crates.io,我可以找到用于规范化和分词的库,但不能找到案例折叠。 regex-syntax确实有case folding code,但它的API中没有公开。

如果没有任何现有的解决方案,那么我可能不得不自己动手

2 个答案:

答案 0 :(得分:2)

unicase crate没有直接公开case折叠,但它提供了一个通用的包装器类型,在不区分大小写的情况下实现EqOrdHash方式。主分支(未发布)支持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指点我这个库。)