Tim*_*ean 15 iterator filterfunction rust map-function rust-result
我有这样的代码:
let things = vec![/* ...*/]; // e.g. Vec<String>
things
.map(|thing| {
let a = try!(do_stuff(thing));
Ok(other_stuff(a))
})
.filter(|thing_result| match *thing_result {
Err(e) => true,
Ok(a) => check(a),
})
.map(|thing_result| {
let a = try!(thing_result);
// do stuff
b
})
.collect::<Result<Vec<_>, _>>()
Run Code Online (Sandbox Code Playgroud)
在语义方面,我想在第一个错误后停止处理.
上面的代码有效,但感觉非常麻烦.有没有更好的办法?我查看了类似的文档filter_if_ok,但我没有找到任何东西.
我知道collect::<Result<Vec<_>, _>>,它很有效.我特意试图消除以下样板:
match的thing_result.我觉得这应该只是一个单行,例如.filter_if_ok(|thing| check(a)).map,我都要包含一个额外的声明let a = try!(thing_result);,以便处理一个可能性Err.再一次,我觉得这可以被抽象出来.map_if_ok(|thing| ...).有没有其他方法可以用来获得这种简洁程度,或者我只是需要强硬一点?
Vee*_*rac 28
有很多方法你可以这么说.
如果你只想恐慌,请使用.map(|x| x.unwrap()).
如果您想要所有结果或单个错误,请collect进入Result<X<T>>:
let results: Result<Vec<i32>, _> = result_i32_iter.collect();
Run Code Online (Sandbox Code Playgroud)
如果您想要除错误之外的所有内容,请使用.filter_map(|x| x.ok())或.flat_map(|x| x).
如果您希望所有内容都出现第一个错误,请使用.scan((), |_, x| x.ok()).
let results: Vec<i32> = result_i32_iter.scan((), |_, x| x.ok());
Run Code Online (Sandbox Code Playgroud)
请注意,在许多情况下,这些操作可以与早期操作结合使用.
从Rust 1.27开始,Iterator::try_for_each可能会引起关注:
一个迭代器方法,该方法将易错函数应用于迭代器中的每个项目,在第一个错误处停止并返回该错误。
也可以将其视为的容易犯错的形式
for_each()或的无状态版本try_fold()。
您可以自己实现这些迭代器.了解标准库中的实现方式filter和map实现方式.
map_ok 执行:
#[derive(Clone)]
pub struct MapOkIterator<I, F> {
iter: I,
f: F,
}
impl<A, B, E, I, F> Iterator for MapOkIterator<I, F>
where
F: FnMut(A) -> B,
I: Iterator<Item = Result<A, E>>,
{
type Item = Result<B, E>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|x| x.map(&mut self.f))
}
}
pub trait MapOkTrait {
fn map_ok<F, A, B, E>(self, func: F) -> MapOkIterator<Self, F>
where
Self: Sized + Iterator<Item = Result<A, E>>,
F: FnMut(A) -> B,
{
MapOkIterator {
iter: self,
f: func,
}
}
}
impl<I, T, E> MapOkTrait for I
where
I: Sized + Iterator<Item = Result<T, E>>,
{
}
Run Code Online (Sandbox Code Playgroud)
filter_ok 几乎是一样的:
#[derive(Clone)]
pub struct FilterOkIterator<I, P> {
iter: I,
predicate: P,
}
impl<I, P, A, E> Iterator for FilterOkIterator<I, P>
where
P: FnMut(&A) -> bool,
I: Iterator<Item = Result<A, E>>,
{
type Item = Result<A, E>;
#[inline]
fn next(&mut self) -> Option<Result<A, E>> {
for x in self.iter.by_ref() {
match x {
Ok(xx) => if (self.predicate)(&xx) {
return Some(Ok(xx));
},
Err(_) => return Some(x),
}
}
None
}
}
pub trait FilterOkTrait {
fn filter_ok<P, A, E>(self, predicate: P) -> FilterOkIterator<Self, P>
where
Self: Sized + Iterator<Item = Result<A, E>>,
P: FnMut(&A) -> bool,
{
FilterOkIterator {
iter: self,
predicate: predicate,
}
}
}
impl<I, T, E> FilterOkTrait for I
where
I: Sized + Iterator<Item = Result<T, E>>,
{
}
Run Code Online (Sandbox Code Playgroud)
您的代码可能如下所示:
["1", "2", "3", "4"]
.iter()
.map(|x| x.parse::<u16>().map(|a| a + 10))
.filter_ok(|x| x % 2 == 0)
.map_ok(|x| x + 100)
.collect::<Result<Vec<_>, std::num::ParseIntError>>()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12306 次 |
| 最近记录: |