#newtype #identifiable #identified-vec #identified-vec-of #via

已删除 identified_vec_macros

这是一个宏,允许您创建 IdentifiedVecOf 新类型,它们的行为类似于 IdentifiedVecOf

1 个不稳定版本

0.1.5 2023年12月16日

#85 in #newtype

MIT 许可证

92KB
1K SLoC

identified_vec

Code Coverage Crates.io Documentation Rust

这是一个独特的可识别元素集合,它保留了插入顺序,灵感来源于 Pointfree的Swift Identified Collections

与标准 Vec 类似,IdentifiedVec 按照特定用户指定的顺序维护其元素。然而,与 Vec 不同,IdentifiedVec 引入了唯一标识元素的能力,使用哈希表确保没有两个元素具有相同的标识符,并有效地查找与特定标识符对应的元素。

IdentifiedVec 当您需要能够通过稳定的标识符高效访问唯一元素时,是 Vec 的有用替代品。它也是 BTreeSet 的有用替代品,其中 Ord 特性要求可能过于严格,是 HashSet 的有用替代品,其中 Hash 特性要求可能过于严格。

您可以使用实现 Identifiable 特性的任何元素类型来创建一个已识别的向量。

示例

extern crate identified_vec;
use identified_vec::{IsIdentifiableVec, IdentifiedVec, Identifiable, IdentifiedVecOf};
use std::cell::RefCell;

#[derive(Eq, PartialEq, Clone, Debug)]
struct User {
    id: &'static str,
    name: RefCell<&'static str>,
}

impl User {
    fn new(id: &'static str, name: &'static str) -> Self {
        Self {
            id,
            name: RefCell::new(name),
        }
    }
    fn name(&self) -> &'static str {
        *self.name.borrow()
    }
}

Identifiable

impl Identifiable for User {
    type ID = &'static str;
    fn id(&self) -> Self::ID {
        self.id
    }
}

from_iter

let mut users = IdentifiedVecOf::<User>::from_iter([
    User::new("u_42", "Satoshi Nakamoto"),
    User::new("u_1337", "Leia Skywalker"),
]);

assert_eq!(
    users.get(&"u_42").map(|u| u.name()),
    Some("Satoshi Nakamoto")
);

assert_eq!(
    users.get_at_index(1).map(|u| u.name()),
    Some("Leia Skywalker")
);

append & elements()

users.append(User::new("u_237", "Alan Turing"));
assert_eq!(
    users.elements(),
    [
        User::new("u_42", "Satoshi Nakamoto"),
        User::new("u_1337", "Leia Skywalker"),
        User::new("u_237", "Alan Turing"),
    ]
    .iter()
    .collect::<Vec<&User>>()
);

// Element with same ID is not appended:
users.append(User::new("u_42", "Tom Mervolo Dolder"));
assert_eq!(
    users.elements(),
    [
        User::new("u_42", "Satoshi Nakamoto"),
        User::new("u_1337", "Leia Skywalker"),
        User::new("u_237", "Alan Turing"),
    ]
    .iter()
    .collect::<Vec<&User>>()
);

update_or_insert

// Element with same ID replaces existing if an `update_*` method is used:
// e.g. `update_or_insert`:
users.update_or_insert(User::new("u_42", "Tom Mervolo Dolder"), 0);
assert_eq!(
    users.elements(),
    [
        User::new("u_42", "Tom Mervolo Dolder"),
        User::new("u_1337", "Leia Skywalker"),
        User::new("u_237", "Alan Turing"),
    ]
    .iter()
    .collect::<Vec<&User>>()
);

update_or_append

// or `update_or_append`
users.update_or_append(User::new("u_237", "Marie Curie"));
assert_eq!(
    users.elements(),
    [
        User::new("u_42", "Tom Mervolo Dolder"),
        User::new("u_1337", "Leia Skywalker"),
        User::new("u_237", "Marie Curie"),
    ]
    .iter()
    .collect::<Vec<&User>>()
);

或者,您可以提供一个闭包来描述元素的标识符

let numbers = IdentifiedVec::<u32, u32>::new_identifying_element(|e| *e);

动机

标准集合中没有任何一个(BTreeSetHashSet)保留了插入顺序,Vec 保留了插入顺序,但它允许有重复项。因此,如果您想有一个保留插入顺序的唯一元素集合(类似Set),则 IdentifiedVec 满足您的需求。甚至更好,元素不需要实现 Hash Ord

标志

此crate具有以下Cargo功能

  • serde:在 IdentifiedVecOf 类型上启用serde序列化支持(其中 Element 实现 Identifiable 特性)。
  • id_prim:为原始类型获取 Identifiable 特质的实现:i8,...,i128u8,...,u128bool(不是很实用,只允许在 IdentifiedVecOf 中有元素,但谁又在乎这些呢。)

实现细节

一个已标识的向量由一个保持插入顺序的 VecID 和一个 HashMap 的 id-元素对组成,以便在给定 ID 的情况下以恒定时间查找元素。

许可证

在 MIT 许可证下授权(LICENSE-MIThttps://open-source.org.cn/licenses/MIT

依赖

约 300–770KB
约 18K SLoC