首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将iter变量重用于条件跳过、过滤等

将iter变量重用于条件跳过、过滤等
EN

Stack Overflow用户
提问于 2021-07-26 03:53:08
回答 2查看 73关注 0票数 2

我有一个迭代器,在最终调用collect()之前,我希望有条件地对其应用过滤器、跳过等。

在另一种语言中,我可能会这样写

代码语言:javascript
复制
// (Rust-like pseudocode)
let mut iter = [1,2,3,4].iter();
if should_filter {
    iter = iter.filter(|x| x % 2 == 0);
}
if should_truncate {
    iter = iter.take(2);
}
iter.collect()

但是因为iter的类型是Iter,而skip()filter()返回的类型是SkipFilter,所以我无法重用iter的原始绑定。因此,我的Rust代码目前看起来像这样:

代码语言:javascript
复制
let iter = [1,2,3,4].iter();

// conditionally filter
if should_filter {
    let iter = iter.filter(|x| x % 2 == 0);

    // conditionally "truncate"
    if should_truncate {
        let iter = iter.take(2);
        return iter.collect();
    }

    return iter.collect();
}

// conditionally "truncate"
if should_truncate {
    let iter = iter.take(2);
    return iter.collect();
}

iter.collect()

有什么方法可以避免这种重复吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-07-26 13:10:20

最简单的解决方案,也可能是最接近你的“其他语言”在幕后所做的事情,是对迭代器进行装箱:

代码语言:javascript
复制
let mut iter: Box<dyn Iterator<Item = &i32>> = Box::new ([1, 2, 3, 4].iter());
if should_filter {
    iter = Box::new (iter.filter(|x| *x % 2 == 0));
}
if should_truncate {
    iter = Box::new (iter.take(2));
}
let v: Vec<_> = iter.collect();

Playground

票数 1
EN

Stack Overflow用户

发布于 2021-07-26 04:13:10

在这种情况下,您可以可靠地信任编译器的优化循环不变量。因为在迭代过程中should_filter不能改变,所以编译器会发现它可以在循环之前检查前提条件,并在should_filtertrue时跳过测试。这意味着您可以简单地将条件放入循环中-这看起来效率很低-并拥有更干净的代码。即使检查没有从循环体中删除,CPU的分支预测器也会很容易地跳过它。类似地,您可以“内联”should_truncate条件:

代码语言:javascript
复制
fn do_stuff(
    inp: impl IntoIterator<Item = u32>,
    should_filter: bool,
    should_truncate: bool,
) -> Vec<u32> {
    inp.into_iter()
        .filter(|x| should_filter && x % 2 == 0)
        .take(if should_truncate { 2 } else { usize::MAX })
        .collect()
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68522044

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档