#iteration #vector #index-iteration

handlevec

在遍历向量时,对索引风格的抽象,支持在迭代过程中进行删除、插入等操作。希望这比手动考虑索引更新更少出现错误和头痛。

1 个不稳定版本

0.1.0 2023 年 6 月 19 日

#1677 in Rust 模式

MIT/Apache

26KB
338

Handlevec

在遍历向量时,对索引风格的抽象,支持在迭代过程中进行删除、插入等操作。希望这比手动考虑索引更新更少出现错误和头痛。

简单示例

use handlevec::mutate_vec_by_handles;

let mut my_vec = vec![1, 4, 9, 16, 25, 36, 49, 64, 81, 100];

mutate_vec_by_handles(&mut my_vec, |mut elem| {
    // Get and copy the next element, if it exists (it must be copied because of the borrow checker.)
    if let Some(n) = elem.peek_forward_slice(1).copied() {
        *elem.get_mut() *= n; // Multiply this element by the next element, in-place.
    } else {
        elem.discard(); // Discard this element if there is no next element
    }
});

assert_eq!(my_vec, vec![4, 36, 144, 400, 900, 1764, 3136, 5184, 8100]);

// Or you can add it as a trait extension, if preferred:
use handlevec::VecMutateByHandles;

my_vec.mutate_vec_by_handles(|mut element| {
    if *element.get() == 900 {
        element.insert_and_skip(50);
    }
});

assert_eq!(my_vec, vec![4, 36, 144, 400, 900, 50, 1764, 3136, 5184, 8100]);

使用 while 循环的示例,如果你不喜欢闭包

use handlevec::VecMutationHandle;

let mut my_vec = vec![2, 3, 4, 5, 6, 11, 1, 5, 7];
let mut my_index = 0;

while let Some(mut elem) = VecMutationHandle::new(&mut my_vec, &mut my_index) {
    if *elem.get() > 10 {
       elem.discard_and_stop_iteration();
    } else {
       elem.set(20);
    }
}

assert_eq!(my_vec, vec![20, 20, 20, 20, 20, 1, 5, 7]);

对于这些示例中的大多数,可能最好使用正常的迭代器,比如 flatmap 或 filter 或 map。这里考虑的特定用例是,如果你有一个更复杂数据类型的向量,其中各种情况可能需要非常不同的处理。

请注意,此包根本不尝试“缓冲”对向量所做的更改。更改是在函数调用时应用的。对于长向量以及大量插入或删除,每次迭代后重新组织向量可能效率不高。

这确实包含 unwraps,但它们绝对不应该通过任何公共 API 的输入访问。如果你从这个 crate 中收到 panic,非常感谢提交错误报告。

功能

  1. 使用上述方法之一(它们是等效的)遍历向量,并对每个元素
  2. 获取当前元素的(可能可变)引用。
  3. 将新值设置到当前元素。
  4. 丢弃当前元素(并返回对该元素的拥有权,但不能对此元素应用其他操作。)
  5. 在当前元素之后插入一个元素,并在下一次迭代中处理它。
  6. 在当前元素之后插入一个元素,但不在下一次迭代中处理它。
  7. 跳过处理特定数量的元素。
  8. 停止迭代。闭包或循环的其余部分仍然执行,因为方法必须返回,但不能处理更多元素。
  9. 丢弃当前元素,并停止迭代。discard 和 stop_iteration 方法都消耗拥有权,因此提供此方法,如果您想同时进行这两项操作。
  10. “查看”向量的一个(可能可变)引用的切片,其中 0 是当前元素的索引。例如,1 是下一个元素,而 0.. 是包括此元素在内的剩余元素切片。
  11. 按正确顺序插入多个元素。(多次调用 insert 会反转插入元素顺序,类似于堆栈的 push。)
  12. 将特定位置的元素替换为另一个元素。
  13. 最后,闭包是一个 FnMut,因此内部循环可以影响闭包之外的可变变量。按照设计,不允许在当前元素之前修改或获取元素。

无运行时依赖