微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决在谓词失败后在迭代器中采用一个额外元素的规范方法是什么?

我有一个 Vec<bool>,我想创建一个迭代器,它停在并包含第一个 false;我该如何实施?我一直在研究 take_while 方法,但它会提前停止一个元素。例如,如果输入是 vec![true,true,false,false],我想要一个等效于 vec![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);

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

解决方法

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。