3 个版本 (破坏性更新)
0.3.0 | 2023 年 12 月 7 日 |
---|---|
0.2.0 | 2023 年 11 月 30 日 |
0.1.0 | 2023 年 11 月 27 日 |
#1398 在 数据结构
21KB
474 代码行
动态列表
一个功能强大且高效的动态列表实现,具有多种数据结构。它设计用于存储任何类型的数据,而不需要额外的成本,因此是各种应用的理想选择。其主要优点之一是避免了动态分发的额外成本。
目前提供两种实现
- 双链表:一种单向链表,能够高效地在两个方向上进行迭代。
- 数组:一个固定大小的数组,其中所有元素都连续存储在堆栈中。
安装 🚀
将以下内容添加到您的 Cargo.toml
[dependencies]
dynamic-list = "0.3.0"
或者,如果您想使用主分支上的最新版本
[dependencies]
dynamic-list = { git = "https://github.com/ferranSanchezLlado/dynamic-list.git" }
用法 🛠️
与 DynamicList
交互的主要方式是通过实现一个允许它通过递归调用自身进行迭代、归约或累加的特制。
示例 1:获取特定元素
use dynamic_list::*;
use typenum::*;
// Chain access:
let array = array![1u8, "hello", true, "world"];
assert_eq!(array.forward().next().value(), &"hello");
assert_eq!(array.backward().value(), &"world");
// Index access:
let list = list![1u8, "hello", true, "world"];
assert_eq!(Index::<U1>::index(list.forward()), &"hello");
assert_eq!(Index::<U3>::index(list.forward()), &"world");
示例 2:我们将一个项目的列表连接成一个字符串
use dynamic_list::{list::Node, *};
// Iterator trait
trait Concat {
fn concat(&self) -> String;
}
impl<V: ToString + Clone> Concat for Node<V> {
fn concat(&self) -> String {
self.value().to_string()
}
}
impl<V: ToString + Clone, N: Concat> Concat for Node<V, N> {
fn concat(&self) -> String {
format!("{}{}", self.value().to_string(), self.next().concat())
}
}
let list = list![1u8, "_hello", -3i32];
assert_eq!(list.forward().concat(), "1_hello-3");
assert_eq!(list.backward().concat(), "-3_hello1");
示例 3:我们想要计算列表中偶数的数量
use dynamic_list::{list::Node, *};
// Polymorphic trait
trait Even {
fn even(&self) -> usize;
}
impl<T: Clone + TryInto<usize>> Even for T {
fn even(&self) -> usize {
(self.clone().try_into().unwrap_or(1) + 1) % 2
}
}
// Iterator trait
trait NumberEven {
fn evens(&self) -> usize;
}
impl<V: Even> NumberEven for Node<V> {
fn evens(&self) -> usize {
self.value().even()
}
}
impl<V: Even + Clone, N: NumberEven> NumberEven for Node<V, N> {
fn evens(&self) -> usize {
self.value().even() + self.next().evens()
}
}
let list = list![false, 1, 2u8, -3, 4isize];
assert_eq!(list.forward().evens(), 3);
限制 ⚠️
虽然 Dynamic List 提供了强大且灵活的解决方案,但了解以下限制是很重要的
- 特制实现要求:为了充分发挥列表的功能,列表中的值必须实现所需的特制。尝试在未实现它们的类型上调用特制方法将导致编译错误,这些错误可能难以解析。然而,随着 Rust 中特制特化的预期引入,这种限制可能得到缓解,允许更灵活的特制实现。例如,可以定义所有类型(除非特别指明)的默认值。值得注意的是,在数组中实现特制目前更为复杂。
- 堆分配:目前,列表中的元素是在堆上分配的。虽然这种方法可以避免在列表中克隆值的需求,但它引入了与堆分配相关的潜在问题。如果堆分配对您的用例是关键考虑因素,您可能希望探索允许单向分配的替代实现,这可能会减少对内存管理的影响。需要注意的是,此限制不适用于基于数组的实现,后者将元素连续存储在字节数组中(可以存储在栈上)。
许可证 📄
本项目可根据您的选择,在以下许可下发布:[MIT 许可证](https://github.com/ferransanchezllado/dynamic-list/blob/6082b159751f7a2fcd494389257ca237e4cbf59d/MIT-LICENSE) 或 [Apache 许可证 2.0](https://github.com/ferransanchezllado/dynamic-list/blob/6082b159751f7a2fcd494389257ca237e4cbf59d/APACHE-LICENSE)。
依赖项
~155KB