Rust可变向量扫描库vec_mut_scan的使用:高效遍历与修改可变向量元素的Rust工具

vec_mut_scan

支持突变和项移除的向量前向扫描。

Vec 提供了一个 VecMutScan 包装器,具有类似迭代器的接口,同时允许突变和移除项。项保持顺序,即使项被移除,每个项最多移动一次。在迭代过程中丢弃 VecMutScan 会保留向量中剩余的项。

这可以看作是 Vecretaindrain 的扩展。它也与不稳定的 drain_filter 非常相似,但稍微更灵活。与 drain_filter 不同,这指定了丢弃行为(保留所有后续元素)。它也不要求在闭包内完成过滤,这提供了额外的灵活性,但代价是无法实现 Iterator 特性。

还提供了一个 VecGrowScan 包装器,扩展了 VecMutScan 以允许在迭代期间插入。这可能需要额外的项移动和临时存储,但仍然在线性时间内运行。

许可证

本软件根据零条款 BSD 许可证提供,请参阅 COPYRIGHT 获取完整的许可信息和此许可证的例外情况。

贡献

除非您明确声明,否则您有意提交包含在此软件中的任何贡献均应按照 COPYRIGHT 中定义的许可进行许可。

元数据

包 URL: pkg:cargo/vec_mut_scan@0.5.0
发布时间: 超过 2 年前
最低 Rust 版本: v1.36.0
许可证: 0BSD
大小: 9.11 KiB

安装

在项目目录中运行以下 Cargo 命令:

cargo add vec_mut_scan

或者将以下行添加到您的 Cargo.toml:

vec_mut_scan = "0.5.0"

文档

docs.rs/vec_mut_scan/0.5.0

仓库

github.com/jix/vec_mut_scan

所有者

  • Jannis Harder (jix)

分类

  • 数据结构
  • 无标准库
  • 算法

完整示例代码

use vec_mut_scan::VecMutScan;

fn main() {
    // 创建一个包含整数的向量
    let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    
    // 创建 VecMutScan 包装器
    let mut scan = VecMutScan::new(&mut vec);
    
    // 遍历并修改元素
    while let Some(item) = scan.next() {
        // 将偶数乘以 2
        if *item % 2 == 0 {
            *item *= 2;
        }
        
        // 移除能被 3 整除的元素
        if *item % 3 == 0 {
            scan.remove();
        }
    }
    
    // 输出结果
    println!("处理后的向量: {:?}", vec);
}
use vec_mut_scan::VecGrowScan;

fn main() {
    // 创建一个包含整数的向量
    let mut vec = vec![1, 2, 3, 4, 5];
    
    // 创建 VecGrowScan 包装器
    let mut scan = VecGrowScan::new(&mut vec);
    
    // 遍历、修改和插入元素
    while let Some(item) = scan.next() {
        // 在偶数后插入新元素
        if *item % 2 == 0 {
            scan.insert_after(*item * 10);
        }
        
        // 在特定值前插入元素
        if *item == 3 {
            scan.insert_before(99);
        }
    }
    
    // 输出结果
    println!("处理后的向量: {:?}", vec);
}
use vec_mut_scan::VecMutScan;

fn main() {
    // 处理字符串向量
    let mut words = vec!["hello", "world", "rust", "programming", "language"];
    let mut scan = VecMutScan::new(&mut words);
    
    // 修改和过滤字符串
    while let Some(word) = scan.next() {
        // 将短字符串转换为大写
        if word.len() < 5 {
            *word = word.to_uppercase().as_str();
        }
        
        // 移除包含特定字符的单词
        if word.contains('r') {
            scan.remove();
        }
    }
    
    println!("处理后的单词: {:?}", words);
}

1 回复

vec_mut_scan:高效遍历与修改可变向量元素的Rust工具

简介

vec_mut_scan是一个专为Rust设计的可变向量扫描库,它提供了高效的方法来遍历和修改可变向量(Vec<T>)中的元素。该库特别适用于需要在遍历过程中同时修改向量元素的场景,避免了传统迭代器可能带来的借用检查器冲突。

主要特性

  • 安全的可变遍历:允许在遍历过程中修改向量元素
  • 高性能:采用底层指针操作,避免不必要的开销
  • 简洁API:提供直观易用的接口
  • 零依赖:纯Rust实现,无外部依赖

安装方法

在Cargo.toml中添加依赖:

[dependencies]
vec_mut_scan = "0.1.0"

基本用法

简单示例

use vec_mut_scan::VecMutScan;

fn main() {
    let mut vec = vec![1, 2, 3, 4, 5];
    
    // 创建可变扫描器
    let mut scanner = VecMutScan::new(&mut vec);
    
    // 遍历并修改元素
    while let Some(element) = scanner.next() {
        *element *= 2; // 将每个元素乘以2
    }
    
    assert_eq!(vec, [2, 4, 6, 8, 10]);
}

带索引的遍历

use vec_mut_scan::VecMutScan;

fn main() {
    let mut vec = vec!["a", "b", "c", "d"];
    let mut scanner = VecMutScan::new(&mut vec);
    
    while let Some((index, element)) = scanner.next_with_index() {
        *element = match index {
            0 => "first",
            1 => "second",
            2 => "third",
            _ => "other"
        };
    }
    
    assert_eq!(vec, ["first", "second", "third", "other"]);
}

条件修改示例

use vec_mut_scan::VecMutScan;

fn main() {
    let mut numbers = vec![1, -2, 3, -4, 5];
    let mut scanner = VecMutScan::new(&mut numbers);
    
    while let Some(num) = scanner.next() {
        if *num < 0 {
            *num = 0; // 将所有负数替换为0
        }
    }
    
    assert_eq!(numbers, [1, 0, 3, 0, 5]);
}

高级用法

跳过元素

use vec_mut_scan::VecMutScan;

fn main() {
    let mut vec = vec![1, 2, 3, 4, 5];
    let mut scanner = VecMutScan::new(&mut vec);
    
    // 跳过前两个元素
    scanner.skip(2);
    
    while let Some(element) = scanner.next() {
        *element += 10;
    }
    
    assert_eq!(vec, [1, 2, 13, 14, 15]);
}

重置扫描器

use vec_mut_scan::VecMutScan;

fn main() {
    let mut vec = vec![1, 2, 3];
    let mut scanner = VecMutScan::new(&mut vec);
    
    // 第一次遍历
    while let Some(element) = scanner.next() {
        *element += 1;
    }
    
    // 重置扫描器重新开始
    scanner.reset();
    
    // 第二次遍历
    while let Some(element) = scanner.next() {
        *element *= 2;
    }
    
    assert_eq!(vec, [4, 6, 8]); // (1+1)*2=4, (2+1)*2=6, (3+1)*2=8
}

完整示例demo

use vec_mut_scan::VecMutScan;

fn main() {
    // 示例1: 基本数值操作
    println!("=== 基本数值操作示例 ===");
    let mut numbers = vec![10, 20, 30, 40, 50];
    let mut scanner = VecMutScan::new(&mut numbers);
    
    while let Some(num) = scanner.next() {
        *num += 5; // 每个元素加5
    }
    println!("加5后的结果: {:?}", numbers);
    
    // 示例2: 字符串处理
    println!("\n=== 字符串处理示例 ===");
    let mut words = vec!["hello", "world", "rust", "programming"];
    let mut word_scanner = VecMutScan::new(&mut words);
    
    while let Some((index, word)) = word_scanner.next_with_index() {
        *word = match index {
            0 => "HELLO",
            1 => "WORLD",
            2 => "RUST",
            _ => "PROGRAMMING"
        };
    }
    println!("处理后的字符串: {:?}", words);
    
    // 示例3: 条件过滤和修改
    println!("\n=== 条件过滤示例 ===");
    let mut scores = vec![85, 92, 78, 60, 95, 88];
    let mut score_scanner = VecMutScan::new(&mut scores);
    
    while let Some(score) = score_scanner.next() {
        if *score < 80 {
            *score = 80; // 将低于80分的分数提升到80分
        }
    }
    println!("调整后的分数: {:?}", scores);
    
    // 示例4: 高级用法组合
    println!("\n=== 高级用法组合示例 ===");
    let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let mut data_scanner = VecMutScan::new(&mut data);
    
    // 跳过前3个元素
    data_scanner.skip(3);
    
    // 修改剩余元素
    while let Some(element) = data_scanner.next() {
        *element *= 10;
    }
    println!("跳过前3个元素后的结果: {:?}", data);
    
    // 重置扫描器并重新处理
    data_scanner.reset();
    while let Some(element) = data_scanner.next() {
        *element += 1;
    }
    println!("重置后再次处理的结果: {:?}", data);
}

#[test]
fn test_vec_mut_scan() {
    // 测试基本功能
    let mut test_vec = vec![1, 2, 3];
    let mut test_scanner = VecMutScan::new(&mut test_vec);
    
    while let Some(element) = test_scanner.next() {
        *element *= 2;
    }
    
    assert_eq!(test_vec, [2, 4, 6]);
    println!("测试通过!");
}

注意事项

  1. 在遍历过程中不要对原始向量进行push/pop操作,这会导致未定义行为
  2. 扫描器在遍历期间会持有向量的可变引用
  3. 适用于需要高性能修改大量元素的场景

性能建议

  • 对于大型向量,vec_mut_scan比传统的iter_mut().enumerate()更高效
  • 避免在循环中创建新的扫描器实例
  • 考虑批量处理来减少函数调用开销

这个库为需要高效遍历和修改可变向量的Rust开发者提供了一个安全且高性能的解决方案。

回到顶部