Rust字符串模糊匹配库rapidfuzz的使用,rapidfuzz提供高效的字符串相似度计算与模糊搜索功能
Rust字符串模糊匹配库rapidfuzz的使用
RapidFuzz是一个通用的字符串匹配库,提供Rust、C++和Python实现。
主要特性
- 多样化的字符串度量:提供多种字符串度量方法,从基于编辑距离的Levenshtein距离到更精细相似度评估的Jaro-Winkler相似度
- 性能优化:库设计时考虑了性能,每个实现都经过精心设计以确保最佳性能,适合分析大型数据集
- 易用性:API设计简单易用,同时仍为优化实现留有空间
安装
安装非常简单:
cargo add rapidfuzz
使用示例
以下是使用Levenshtein距离的示例。其他度量方法可以在fuzz
和distance
模块中找到。
use rapidfuzz::distance::levenshtein;
// 使用Levenshtein距离进行简单比较
assert_eq!(
3,
levenshtein::distance("kitten".chars(), "sitting".chars())
);
// 如果确定输入字符串仅包含ASCII字符,通常对字节操作更快
assert_eq!(
3,
levenshtein::distance("kitten".bytes(), "sitting".bytes())
);
// 可以提供score_cutoff值来过滤掉距离比score_cutoff更差的字符串
assert_eq!(
None,
levenshtein::distance_with_args(
"kitten".chars(),
"sitting".chars(),
&levenshtein::Args::default().score_cutoff(2)
)
);
// 可以提供score_hint告诉实现预期的分数
// 这可以用来在内部选择更高效的实现,但当距离实际上比score_hint更差时可能会导致性能下降
assert_eq!(
3,
levenshtein::distance_with_args(
"kitten".chars(),
"sitting".chars(),
&levenshtein::Args::default().score_hint(2)
)
);
// 当比较单个字符串与多个字符串时,可以使用提供的`BatchComparators`
// 这些可以缓存部分计算结果,提供显著的加速
let scorer = levenshtein::BatchComparator::new("kitten".chars());
assert_eq!(3, scorer.distance("sitting".chars()));
assert_eq!(0, scorer.distance("kitten".chars()));
完整示例代码
use rapidfuzz::distance::levenshtein;
fn main() {
// 基本字符串比较
let distance = levenshtein::distance("rust".chars(), "rusty".chars());
println!("Distance between 'rust' and 'rusty': {}", distance); // 输出: 1
// 使用字节比较(ASCII字符串)
let byte_distance = levenshtein::distance("rust".bytes(), "Rust".bytes());
println!("Distance between 'rust' and 'Rust' (bytes): {}", byte_distance); // 输出: 1
// 使用score_cutoff过滤结果
let filtered_distance = levenshtein::distance_with_args(
"hello".chars(),
"world".chars(),
&levenshtein::Args::default().score_cutoff(3)
);
println!("Filtered distance: {:?}", filtered_distance); // 输出: None
// 批量比较器
let names = vec!["Robert", "Rupert", "Rubin", "Robin"];
let scorer = levenshtein::BatchComparator::new("Rust".chars());
for name in names {
let dist = scorer.distance(name.chars());
println!("Distance between 'Rust' and '{}': {}", name, dist);
}
// 输出:
// Distance between 'Rust' and 'Robert': 4
// Distance between 'Rust' and 'Rupert': 3
// Distance between 'Rust' and 'Rubin': 3
// Distance between 'Rust' and 'Robin': 3
}
扩展示例:使用多种字符串度量方法
use rapidfuzz::{distance::levenshtein, fuzz::ratio};
fn main() {
// 1. 使用Levenshtein距离
let lev_dist = levenshtein::distance("book".chars(), "back".chars());
println!("Levenshtein距离: {}", lev_dist); // 输出: 2
// 2. 使用比率相似度
let similarity = ratio("hello world".chars(), "hello word".chars());
println!("相似度比率: {}", similarity); // 输出: 95
// 3. 带权重的比较
let weighted_dist = levenshtein::distance_with_args(
"color".chars(),
"colour".chars(),
&levenshtein::Args::default()
.weights(1, 1, 2) // 插入、删除、替换的权重
);
println!("带权重的距离: {}", weighted_dist); // 输出: 1
// 4. 批量处理多个字符串
let targets = ["apple", "aple", "appl", "peach", "peal"];
let query = "apple";
let scorer = levenshtein::BatchComparator::new(query.chars());
println!("与'{}'的Levenshtein距离:", query);
for target in targets {
let dist = scorer.distance(target.chars());
println!("- {}: {}", target, dist);
}
// 输出:
// - apple: 0
// - aple: 1
// - appl: 1
// - peach: 3
// - peal: 3
}
许可证
根据Apache许可证2.0版或MIT许可证授权使用。除非您明确声明,否则您有意提交的任何贡献都应按上述方式双重许可,不附加任何额外条款或条件。
1 回复
Rust字符串模糊匹配库rapidfuzz使用指南
rapidfuzz是一个高效的Rust字符串模糊匹配库,提供多种字符串相似度计算算法和模糊搜索功能。它是Python库RapidFuzz的Rust实现,性能优异且功能丰富。
主要特性
- 多种相似度算法:Levenshtein、Jaro、Jaro-Winkler等
- 高性能:经过优化,处理速度快
- 支持Unicode
- 模糊搜索功能
- 可自定义权重和评分
安装
在Cargo.toml中添加依赖:
[dependencies]
rapidfuzz = "0.12"
完整示例代码
下面是一个综合使用rapidfuzz功能的完整示例:
use rapidfuzz::distance::{levenshtein, jaro_winkler};
use rapidfuzz::fuzz;
use rapidfuzz::process;
fn main() {
// 示例1: 计算Levenshtein距离和相似度
let str1 = "kitten";
let str2 = "sitting";
let distance = levenshtein::distance(str1.chars(), str2.chars());
println!("Levenshtein距离: {}", distance); // 输出: 3
let score = levenshtein::normalized_similarity(str1.chars(), str2.chars());
println!("相似度分数: {}", score); // 输出: 57.14285714285714
// 示例2: 使用Jaro-Winkler相似度
let str3 = "martha";
let str4 = "marhta";
let jw_score = jaro_winkler::similarity(str3.chars(), str4.chars());
println!("Jaro-Winkler相似度: {}", jw_score); // 输出: 0.9611111111111111
// 示例3: 模糊搜索
let choices = vec!["apple", "banana", "orange", "grape", "melon"];
let query = "appl";
let best_match = process::extract_one(
query,
&choices,
fuzz::ratio,
process::ExtractOptions::default()
);
match best_match {
Some((choice, score, _)) => {
println!("最佳匹配: {} (分数: {})", choice, score); // 输出: 最佳匹配: apple (分数: 90)
}
None => println!("没有找到匹配"),
}
// 示例4: 带权重的部分匹配
let food_choices = vec![
"apple pie",
"banana bread",
"orange juice",
"grape soda",
"melon ball"
];
let food_query = "apple";
let best_partial = process::extract_one(
food_query,
&food_choices,
levenshtein::partial_ratio,
process::ExtractOptions::default()
);
match best_partial {
Some((choice, score, _)) => {
println!("最佳部分匹配: {} (分数: {})", choice, score); // 输出: 最佳部分匹配: apple pie (分数: 100)
}
None => println!("没有找到匹配"),
}
// 示例5: 自定义权重
let weights = levenshtein::EditWeights {
insertion_cost: 1,
deletion_cost: 1,
substitution_cost: 2, // 替换代价更高
};
let weighted_distance = levenshtein::distance_with_weights(
str1.chars(),
str2.chars(),
&weights
);
println!("自定义权重距离: {}", weighted_distance); // 输出: 5
// 示例6: 批量处理
let fruit_choices = vec![
"apple",
"banana",
"orange",
"grape",
"melon",
"pineapple",
"strawberry"
];
let fruit_query = "appl";
// 获取前3个最佳匹配
let top_matches = process::extract(
fruit_query,
&fruit_choices,
fuzz::ratio,
process::ExtractOptions::default()
.limit(3) // 限制结果数量
.score_cutoff(70) // 最低分数阈值
);
println!("前3个匹配结果:");
for (choice, score, _) in top_matches {
println!("- {} (分数: {})", choice, score);
}
/* 输出:
前3个匹配结果:
- apple (分数: 90)
- pineapple (分数: 72)
*/
}
性能建议
- 对于大量重复比较,考虑将字符串预处理为
Vec<char>
或使用StrWrapper
- 根据场景选择合适的算法:
- 短字符串:Levenshtein
- 长字符串:Jaro或Jaro-Winkler
- 部分匹配:partial_ratio
- 设置合理的score_cutoff可以显著提高性能
rapidfuzz是处理字符串模糊匹配的强大工具,适用于拼写检查、搜索建议、数据清洗等多种场景。