4个稳定版本
1.0.3 | 2022年2月28日 |
---|
#905 在 数据结构
28KB
326 行
ord-by-set
一个提供编译时配置排序方案的弱排序多重集合库。
何时使用此库
- 当你想要一个
BTreeSet
,但你的数据涉及部分/松散等价,并且你想要能够高效地检索多个松散等价值时。 - 当你有与值相同类型的有序键时,允许有内联键的类似
BTreeMap
的数据结构。- 这是通过使用自定义的
Order
实现来完成的,以便按照用作键的字段对类型进行排序,而不依赖于完全排序。
- 这是通过使用自定义的
- 当你想要一个多-{集合,映射},但哈希不是一个选项时。
不适用于此
- 在不需要多个松散等价值时,不要用此库代替
HashMap
/HashSet
/BTreeMap
/BTreeSet
。
概述
OrdBySet
由两部分组成:其存储后端(一个排序的 Vec<T>
)和一个用户提供的排序器。排序器是一个可以接受两个项目并松散比较它们的值。这是通过 Order<T>
trait 完成的,它要求一个方法,即 Order::order_of
fn order_of(&self, left: &T, right: &T) -> Ordering;
然而,与 Ord
不同,这并不保证是完全排序的,因此它可以以这种方式使用,将松散等价值分组,类似于如何使用 包数据结构 存储多个相同的值。
然而,不同的特性是,然后可以继续查询所有松散等价类型。排序方案。
[^1]: 一个例子是,你可能希望查询3的结果同时显示整数3和字符串3,同时仍然存储字符串和整数。有关更多信息,请参阅 Order
的文档。
示例
use ord_by_set::OrdBySet;
// Our orderer will be a simple function that sorts based on the first 5 characters
let ordering_fn = |left: &&str, right: &&str| left[..5].cmp(&right[..5]);
let set = OrdBySet::new_with_order(ordering_fn)
.with_items(["00001_foo", "00001_bar", "00002_foo"]);
let id_1_subset = set.get(&"00001").unwrap();
// id_1_subset = unordered(["00001_foo", "00001_bar"])
assert_eq!(id_1_subset.len(), 2);
assert!(id_1_subset.contains(&"00001_bar"));
assert!(id_1_subset.contains(&"00001_foo"));
虽然上述示例使用闭包作为排序器,但如果你实现了 Order<T>
,则可以是任何类型。通常,这通过一个 零大小类型 实现,因为通常排序机制不需要状态,只需要行为。
use ord_by_set::{OrdBySet, Order};
use std::cmp::Ordering;
#[derive(Default)]
struct EverythingEqual;
impl<T> Order<T> for EverythingEqual {
fn order_of(&self, _: &T, _: &T) -> Ordering {
Ordering::Equal
}
}
type AllEqualSet = OrdBySet<i32, EverythingEqual>;
let mut set = AllEqualSet::new().with_items([3, 5, 2, 7]);
assert_eq!(set.count(&30), 4);
set.remove_all(&0);
assert!(set.is_empty());