在谓词失败后,在迭代器中获取一个额外元素的规范方法是什么?

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

我有一个

Vec<bool>
,我想创建一个迭代器,该迭代器停在并包含第一个
false
;我怎样才能实现它?我一直在研究
take_while
方法,但它提前停止了一个元素。例如,如果输入是
vec![true, true, true, false, false]
,我想要一个与
vec![true, true, true, false].iter()
等效的迭代器,但我找不到以函数方式表达它的好方法。我考虑过以下方法:

// method 1
// This one triggers the side effects of do_something_with_x
// for the right elements, but it seems like bad style. It
// also doesn't give me an iterator that I can chain on, I
// would need to use the side effect creatively.
input
    .iter()
    .map(|x| {
        do_something_with_x(x);
        x
    })
    .take_while(|x| *x)
    .for_each(|_|());

// method 2
// This seems a little better, but I don't like how I have
// to iterate through it twice. My code isn't performance
// sensitive so that's not the reason, but it just looks bad to me.
let len = input.iter().position(|x| !*x);
let result = input.iter().take(len);

我已经显着简化了问题以使其更容易理解,向量是不同的类型,并且我正在使用不同的谓词。我还在考虑第三种方法,该方法涉及压缩同一事物的两个迭代器,这些迭代器偏移一,但我不太确定如何最好地实现它,而且无论如何它似乎都不太可读。解决此类问题的规范方法是什么?

rust iterator
2个回答
3
投票

您可以使用

Iterator::scan
,它通过调用每个项目和可变状态的闭包来生成一个新的迭代器。

通过让状态指示我们是否应该在下一个项目结束,我们可以在第一个虚假项目之后停止:

input
    .iter()
    .scan(false, |is_done, item| {
        if *is_done { return None; }
        if !item { *is_done = true; }
        Some(item)
    })
    .for_each(|_| {});

0
投票

itertools 板条箱有

take_while_inclusive
功能,正是这样做的。引用:“返回一个迭代器适配器,该适配器在给定谓词为
true
时消耗元素,包括谓词首先为其返回
false
的元素。”

© www.soinside.com 2019 - 2024. All rights reserved.