如何计算迭代器适配器链中过滤元素的数量

问题描述 投票:0回答:1

我有一个应用于初始迭代器的迭代器适配器链(我不知道编译时的数量)。 一个简化的示例是通过整除性过滤一系列数字并获取最后剩余数字的数量:

    let n: usize = 10;
    let mut iter_chain: Box<dyn std::iter::Iterator<Item = usize>> = Box::new(1..=n);

    for i in 2..n {
        iter_chain = Box::new(iter_chain.filter(move |j| j % i != 0));
    }

    println!("{}", iter_chain.count());

现在,我想计算该过滤器链的每个stage中的元素数量

我的想法是在每个过滤器之间插入一个

inspect

适配器,增加相应
阶段的计数器。 然而,每个 inspect
 适配器都必须从循环之外的某个地方借用可变计数器。
这导致了我当前存储计数器的 Vector 的多次相互借用。

let n: usize = 10; let mut iter_chain: Box<dyn std::iter::Iterator<Item = usize>> = Box::new(1..=n); let mut filter_overview = vec![0; n]; for i in 2..n { // cannot borrow `filter_overview` as mutable more than once at a time // | // V iter_chain = Box::new(iter_chain.inspect(|_| filter_overview[i] += 1)); iter_chain = Box::new(iter_chain.filter(move |j| j % i != 0)); } println!("{filter_overview:?} {}", iter_chain.count());
本例中 

filter_overview

 的预期值为 
[10, 5, 3, 3, 2, 2, 1, 1]

这个问题有解决方法吗,或者我是否必须使用与 Vector 不同的东西来存储这些计数器? 也许有一种完全不同的方法来实现这一目标?

游乐场

rust filter iterator mutable borrow
1个回答
0
投票
您可以使用内部可变性或原子来做到这一点。对于原子,向量变成

Arc<Vec<AtomicU64>>

 (或您选择的任何原子类型)。结果看起来像(
Playground 链接):

use std::sync::{ atomic::{AtomicU64, Ordering}, Arc, }; fn main() { let n: usize = 10; let mut iter_chain: Box<dyn Iterator<Item = usize>> = Box::new(1..=n); // AtomicU64 isn't Clone, so can't use vec![] syntax. let filter_overview = Arc::new(Vec::from_iter( std::iter::repeat_with(|| AtomicU64::new(0)) .take(n) )); for i in 2..n { // Get a fresh reference by cloning the Arc. let overview = filter_overview.clone(); // Use a move closure to move the new Arc into the iterator. iter_chain = Box::new(iter_chain.inspect(move |_| { overview[i].fetch_add(1, Ordering::Relaxed); })); iter_chain = Box::new(iter_chain.filter(move |j| j % i != 0)); } println!("{filter_overview:?} {}", iter_chain.count()); println!("Desired output: {:?}", [10, 5, 3, 3, 2, 2, 1, 1]); }
输出是

[0, 0, 10, 5, 3, 3, 2, 2, 1, 1] 1 Desired output: [10, 5, 3, 3, 2, 2, 1, 1]
    
© www.soinside.com 2019 - 2024. All rights reserved.