2 个版本

0.1.1 2023 年 12 月 2 日
0.1.0 2023 年 12 月 2 日

#1418算法

MIT 许可证

165KB
3.5K SLoC

📐 norm

Latest version Docs badge CI

norm 是字符串上不同距离度量的集合。这个问题有时被称为“字符串相似度搜索”,或更通俗地说是“模糊匹配”。

可用度量

  • FzfV1:fzf 使用 --algo=v1 启动时使用的算法的移植;
  • FzfV2:fzf 在没有任何额外标志或使用 --algo=v2 启动时使用的算法的移植;

性能

性能是这个crate的首要任务。我们的目标是提供每个度量算法的最快实现,跨越所有语言。 这里 你可以找到一些比较 norm 的度量与其他度量以及其他流行库的基准。

示例用法

use std::ops::Range;

use norm::fzf::{FzfParser, FzfV2};
use norm::Metric;

let mut fzf = FzfV2::new();

let mut parser = FzfParser::new();

let query = parser.parse("aa");

let cities = ["Geneva", "Ulaanbaatar", "New York City", "Adelaide"];

let mut results = cities
    .iter()
    .copied()
    .filter_map(|city| fzf.distance(query, city).map(|dist| (city, dist)))
    .collect::<Vec<_>>();

// We sort the results by distance in ascending order, so that the best match
// will be at the front of the vector.
results.sort_by_key(|(_city, dist)| *dist);

assert_eq!(results.len(), 2);
assert_eq!(results[0].0, "Adelaide");
assert_eq!(results[1].0, "Ulaanbaatar");

// We can also find out which sub-strings of each candidate matched the query.

let mut ranges: Vec<Range<usize>> = Vec::new();

let _ = fzf.distance_and_ranges(query, results[0].0, &mut ranges);
assert_eq!(ranges.len(), 2);
assert_eq!(ranges[0], 0..1); // "A" in "Adelaide"
assert_eq!(ranges[1], 4..5); // "a" in "Adelaide"

ranges.clear();

let _ = fzf.distance_and_ranges(query, results[1].0, &mut ranges);
assert_eq!(ranges.len(), 1);
assert_eq!(ranges[0], 2..4); // The first "aa" in "Ulaanbaatar"

关于crate命名方案的说明

norm的package.namenorms,而其lib.namenorm。这是因为包名必须是唯一的才能发布到 crates.io,但不幸的是 norm 已经被一个crate占领者占用。这意味着你应该在 Cargo.toml 中将 norm 导入为 norms,并在源代码中将它用作 norm

例如

# Cargo.toml
[dependencies]
norms = { version = "0.1", features = ["fzf-v2"] }
// main.rs
use norm::fzf::FzfV2;

fn main() {
    println!("{:?}", FzfV2::new());
}

依赖项

~110–250KB