满足条件后短路迭代器



我正在尝试编写一个迭代器,它有条件地使用单独迭代器中的元素。在我的示例中,单独的迭代器应该递增sum变量。一旦满足另一个条件*n == 4,迭代器应该停止检查该条件,并假设其余元素是sum变量的增量。我有以下工作示例:

fn conditional(n: &i64) -> bool {
// a lot of code here which is omitted for brevity
n % 2 == 0
}
fn main() {
let buf = vec![1,2,3,4,5,6];

let mut sum = 0;

let mut iter = buf.iter();

while let Some(n) = iter.next() {
if conditional(n) {
sum += n;
}
if *n == 4 {
// end of file - assume rest of elements are `conditional`
break;
}
};

// rest of elements [5,6]
for n in iter {
sum += n;
}
println!("sum (2+4+5+6): {:?}", sum);
}

输出:

sum (2+4+5+6): 17

游乐场连接

我宁愿用一个迭代器来写同样的东西,比如flat_map:

fn conditional(n: &i64) -> bool {
// a lot of code here which is omitted for brevity
n % 2 == 0
}
fn main() {
let buf = vec![1,2,3,4,5,6];
let mut sum = 0;
let mut terminate = false;
buf.iter().flat_map(|n| {
if *n == 4 {
// hard terminate here - return Some(n) for rest of iterator [5,6]
terminate = true;
return Some(n);
}
if terminate {
return Some(n);
}
if conditional(n) {
return Some(n);
}
None // odd
})
.for_each(|n| {
sum += n;
});
println!("sum (2+4+5+6): {:?}", sum);
}

输出:

sum (2+4+5+6): 17

游乐场连接

有没有办法用更简洁的方式写这篇文章?一旦达到*n == 4条件,我想使迭代器短路。

有很多方法可以解决这个问题。

这里有一对:

fn conditional(n: &i64) -> bool {
// a lot of code here which is omitted for brevity
n % 2 == 0
}
fn main() {
let buf = vec![1, 2, 3, 4, 5, 6];
let sum = buf
.iter()
.fold((0, false), |(mut sum, mut terminate), value| {
if *value == 4 {
terminate = true;
}
if terminate || conditional(value) {
sum += *value;
}
(sum, terminate)
})
.0;
println!("sum (2+4+5+6): {:?}", sum);
}
sum (2+4+5+6): 17

或者使用filter和有状态闭包:

fn conditional(n: &i64) -> bool {
// a lot of code here which is omitted for brevity
n % 2 == 0
}
fn main() {
let buf = vec![1, 2, 3, 4, 5, 6];
let sum: i64 = buf
.iter()
.filter({
let mut terminate = false;
move |&value| {
terminate || {
if *value == 4 {
terminate = true;
}
conditional(value)
}
}
})
.sum();
println!("sum (2+4+5+6): {:?}", sum);
}
sum (2+4+5+6): 17

您可以使用filter():

buf.iter().filter(|n| {
if **n == 4 {
terminate = true;
}
terminate || conditional(n)
})

sum()代替for_each():

let sum = buf
.iter()
.filter(|n| {
if **n == 4 {
terminate = true;
}
terminate || conditional(n)
})
.sum::<i64>();

最新更新