2 个版本
0.2.1 | 2022 年 2 月 28 日 |
---|---|
0.2.0 | 2021 年 12 月 6 日 |
0.1.0 |
|
#1534 in 数据结构
23KB
472 行
prefix_tree_map
A Rust 实现的通用前缀树(trie)映射,支持通配符捕获。
优缺点
优点
- 快速高效
- 通配符捕获支持 - 在匹配时捕获映射中的通配符字符。
- 泛化 - 支持任何类型的键和值,只要键部分实现了
Ord
和Clone
特性。 - 捕获映射定制 - 自定义通配符捕获的键部分存储方式。
- 查找操作中无递归 - 由于键可能是一个巨大的数据结构,为了避免栈溢出,这个前缀树映射只存储那些用于回溯的小型通配符节点指针,而不是存储每个节点搜索的整个上下文。
缺点
- 映射本身是不可变的,因为映射构建器在插入节点时使用二叉堆进行排序。我们无法在二叉堆上获取任何项而不进行整个迭代。一旦调用
build()
,二叉堆将转换为排序后的Vec
。我们不能在不排序的情况下向Vec
中推送任何项。 - 单个通配符不能匹配多次。这意味着
word
只能由w**d
匹配,不能由w*d
匹配。
用法
use prefix_tree_map::PrefixTreeMapBuilder;
let mut map_builder = PrefixTreeMapBuilder::new();
// To insert an exact key path, call `insert_exact()`
map_builder.insert_exact(["path", "to", "value"], "value0");
// Insert into a existed key path could overwrite the value in it
map_builder.insert_exact(["path", "to", "value"], "value1");
// To insert an key path with wildcards, mark key parts using `prefix_tree_map::KeyPart` and call `insert()`
use prefix_tree_map::KeyPart;
map_builder.insert(
[
KeyPart::Exact("path"),
KeyPart::Wildcard("to"),
KeyPart::Exact("value"),
],
"value2",
);
// Anything implemented trait `FromIterator` can be inserted as a key path:
let path = "path/to/anothor/value";
map_builder.insert_exact(path.split('/'), "value3");
let anothor_path = "path/to/:some/value";
map_builder.insert(
anothor_path.split('/').map(|part| {
if part.starts_with(':') {
KeyPart::Wildcard(part)
} else {
KeyPart::Exact(part)
}
}),
"value4",
);
// Then build the map
let map = map_builder.build();
// Find a value without matching any wildcard part
assert_eq!(
Some(&"value3"),
map.find_exact(&["path", "to", "anothor", "value"])
);
// Find a value with matching wildcard part
assert_eq!(Some(&"value4"), map.find(&["path", "to", "a", "value"]));
// `KeyPart::Exact` has a higher match priority than `KeyPart::Wildcard`
assert_eq!(Some(&"value3"), map.find(&["path", "to", "anothor", "value"]));
// Find a value with matching wildcard part, and store captured matched wildcard parts in a map
use std::collections::HashMap;
let mut captures = HashMap::new();
assert_eq!(
Some(&"value4"),
map.find_and_capture(&["path", "to", "a", "value"], &mut captures)
);
assert_eq!(Some(&"a"), captures.get(&":some"));
定制捕获映射
struct Map {
pub data: [Option<String>; 2],
}
impl Map {
fn new() -> Self {
Self { data: [None, None] }
}
}
use prefix_tree_map::Captures;
impl Captures<&str, &str> for Map {
fn insert(&mut self, key: &str, value: &str) {
match key {
":user_id" => self.data[0] = Some(value.to_string()),
":product_id" => self.data[1] = Some(value.to_string()),
_ => (),
}
}
}
fn capture() {
use prefix_tree_map::{KeyPart, PrefixTreeMapBuilder};
let mut builder = PrefixTreeMapBuilder::new();
builder.insert(
[
KeyPart::Exact("user"),
KeyPart::Wildcard(":user_id"),
KeyPart::Exact("home"),
],
"user",
);
builder.insert(
[
KeyPart::Exact("product"),
KeyPart::Wildcard(":product_id"),
KeyPart::Exact("info"),
],
"product",
);
let map = builder.build();
let mut captures = Map::new();
map.find_and_capture(
&"/user/00000/home".split('/').collect::<Vec<_>>(),
&mut captures,
);
assert_eq!("00000", captures.data[0].as_ref().unwrap());
}
有关更多信息,请参阅 examples/router.rs
no_std
通过在 Cargo.toml
中禁用 default-features
来取消 std
功能,以删除 Rust 标准库依赖。
示例
查看 示例。
许可证
GNU 通用公共许可证 v3.0