#range #key #key-value #map #overlapping #structures #contiguous

rangemap

将键存储为范围的映射和集合数据结构。连续和重叠的范围映射到相同的值将合并为单个范围

26 个版本 (11 个稳定)

1.5.1 2024年2月27日
1.4.0 2023年9月18日
1.3.0 2023年1月3日
1.2.0 2022年12月26日
0.1.3 2019年2月25日

#12 in 数据结构

Download history 48449/week @ 2024-04-23 47969/week @ 2024-04-30 48385/week @ 2024-05-07 49798/week @ 2024-05-14 53360/week @ 2024-05-21 58653/week @ 2024-05-28 53781/week @ 2024-06-04 51013/week @ 2024-06-11 56400/week @ 2024-06-18 63498/week @ 2024-06-25 52557/week @ 2024-07-02 61177/week @ 2024-07-09 60333/week @ 2024-07-16 62728/week @ 2024-07-23 56794/week @ 2024-07-30 57056/week @ 2024-08-06

249,434 每月下载量
219 个crate中(36个直接) 使用

MIT/Apache

215KB
4K SLoC

rangemap

Crate Docs Build status Rust

RangeMapRangeInclusiveMap 是以范围为键的映射数据结构。连续和重叠的范围映射到相同的值将合并为单个范围。

还提供了相应的 RangeSetRangeInclusiveSet 结构。

不同类型的范围

RangeMapRangeInclusiveMap 分别对应于标准库中的 RangeRangeInclusive 类型。对于某些应用程序,范围类型的选取可能是明显的,甚至可能由现有的设计决策所决定。对于其他应用程序,选取可能似乎是随机的,而是由便利性或审美偏好所指导。

如果您的案例中不明显,请考虑以下差异

  • 如果您的密钥类型 K 表示连续体上的点(例如 f64),并且哪个相邻范围“拥有”它们接触的值的选择在很大程度上是任意的,那么使用半开区间 Range(如 0.0..1.01.0..2.0)可能更自然。如果您在这里使用封闭的 RangeInclusive,那么为了表示这两个相邻的范围,您需要从较早的范围的末尾减去一些无穷小值(这可能与 f64 的情况一样,取决于 K 的具体值)。有关此问题的更多内容,请参阅下面的最后一点。
  • 如果您需要表示包含密钥域最大值(例如 255u8)的范围,那么您可能希望使用 RangeInclusive,如 128u8..=255u8。有时可以通过使用比您实际尝试表示的值更宽的密钥类型(例如 K=u16,尽管您只想表示覆盖 u8 的范围)来解决这个问题,但这些情况下密钥域通常代表离散对象,而不是连续体上的点,因此 RangeInclusive 可能是表达这些范围的更自然方式。
  • 如果您使用 RangeInclusive,则必须能够为您的密钥类型 K 定义 后继前驱 函数,因为不能通过测试它们的端点是否相等来检测相邻范围(从而合并它们)。对于表示连续体上的点的密钥类型,定义这些函数可能很棘手且容易出错。对于表示离散对象的密钥类型,这通常要简单得多。

示例:与 Chrono 一起使用

use chrono::offset::TimeZone;
use chrono::{Duration, Utc};
use rangemap::RangeMap;

fn main() {
    let people = ["Alice", "Bob", "Carol"];
    let mut roster = RangeMap::new();

    // Set up initial roster.
    let start_of_roster = Utc.ymd(2019, 1, 7);
    let mut week_start = start_of_roster;
    for _ in 0..3 {
        for person in &people {
            let next_week = week_start + Duration::weeks(1);
            roster.insert(week_start..next_week, person);
            week_start = next_week;
        }
    }

    // Bob is covering Alice's second shift (the fourth shift overall).
    let fourth_shift_start = start_of_roster + Duration::weeks(3);
    let fourth_shift_end = fourth_shift_start + Duration::weeks(1);
    roster.insert(fourth_shift_start..fourth_shift_end, &"Bob");

    for (range, person) in roster.iter() {
        println!("{} ({}): {}", range.start, range.end - range.start, person);
    }

    // Output:
    // 2019-01-07UTC (P7D): Alice
    // 2019-01-14UTC (P7D): Bob
    // 2019-01-21UTC (P7D): Carol
    // 2019-01-28UTC (P14D): Bob
    // 2019-02-11UTC (P7D): Carol
    // 2019-02-18UTC (P7D): Alice
    // 2019-02-25UTC (P7D): Bob
    // 2019-03-04UTC (P7D): Carol
}

软件包功能

默认情况下,此软件包不依赖于其他软件包。

如果您启用 serde1 功能,它将引入对 serde 软件包的依赖,并为该软件包中的所有映射和集合类型提供 SerializeDeserialize 实现。

您可以在 Cargo.toml 文件中这样启用 serde1 功能

[dependencies]
rangemap = { version = "1", features = ["serde1"] }

在没有 Rust 标准库的情况下构建

此软件包可以在没有完整标准库的情况下工作(例如在没有操作系统的裸机运行时),但依赖于全局分配器——即它链接了 corealloc 软件包,但没有 std

目前该软件包中没有需要标准库的功能。此类功能可能会在将来引入,并且将受默认启用 std 功能的限制。

有关在没有标准库的情况下操作的一般信息,请参阅《Rust 编程语言》书籍。

依赖项

~165KB