gpt4 book ai didi

rust - 在迭代器上使用 count() -> Result 函数的最佳方法?

转载 作者:行者123 更新时间:2023-11-29 08:33:04 25 4
gpt4 key购买 nike

我想做这样的事情:

let count = self.line_current[self.line_current_pos..]
.split(self.separator)
.take(i_count)
.map(|s|if s.is_empty() { Ok(()) } else { Err(s) })
.count()?;
if count != i_count {
Err("Unexpected newline")
} else {
Ok(())
}

这是面向行的解析函数,它会跳过预期数量的分隔符。

然而,迭代器上的 count() 函数会消耗迭代器并且不能与 std::ops::Try 一起使用。有没有一种优雅的方法来计算有效项目,但如果其中一个项目不符合条件则立即返回错误?

最佳答案

假设您要解析 "field1,field2,A,B,C" 形式的字符串- 所以开头有一些你想跳过的垃圾字段(在这种情况下是 2 个),但你也希望它后面有 3 个标记 - 如果存在的字段少于 3 个,你想出错。

此类函数的签名如下所示:

fn parse(line: &str, skip: usize, count: usize) -> Result<Vec<Token>, Error>

在这种情况下,我们会调用 parse("field1,field2,A,B,C", 2, 3) .

所以我们首先将字符串拆分为 ',' :

line.split(',')

我们跳过skip字段:

    .skip(skip)

我们尝试解析每个字段

    .map(str::parse)

现在是优雅的技巧 - 将一个元素附加到迭代器的末尾,如果我们到达它就会导致错误。我们使用 Iterator::chainSome(T) - Some(T)在这种情况下,其功能类似于一个元素的迭代器。

    .chain(Some(Err(Error::NotEnoughTokens)))

不管我们需要多少元素

    .take(count)

将整个东西收集到 Result<Vec<Token>, Error> 中- 这很管用!返回的错误将是第一个遇到的,所以首先遇到任何解析错误,然后是 NotEnoughTokens错误。

    .collect()

使用它的完整代码,包括 token 解析样板,如下所示:

use std::str::FromStr;

#[derive(Debug)]
enum Token {
A,
B,
C,
}

#[derive(Debug)]
enum Error {
NotEnoughTokens,
InvalidToken,
}

impl FromStr for Token {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Error> {
match s {
"A" => Ok(Token::A),
"B" => Ok(Token::B),
"C" => Ok(Token::C),
_ => Err(Error::InvalidToken),
}
}
}

fn parse(line: &str, skip: usize, count: usize) -> Result<Vec<Token>, Error> {
line.split(',')
.skip(skip)
.map(str::parse)
.chain(Some(Err(Error::NotEnoughTokens)))
.take(count)
.collect()
}

fn main() {
println!("{:?}", parse("A,B,C", 0, 2)); // Ok([A, B])
println!("{:?}", parse("A,B,C", 0, 3)); // Ok([A, B, C])
println!("{:?}", parse("A,B,C", 0, 4)); // Err(NotEnoughTokens)
println!("{:?}", parse("A,B,C,D", 0, 4)); // Err(InvalidToken)

println!("{:?}", parse("field1,B,C", 1, 2)); // Ok([B, C])
println!("{:?}", parse("field1,field2,C", 2, 1)); // Ok([C])
println!("{:?}", parse("field1,B,C", 2, 2)); // Err(NotEnoughTokens)
println!("{:?}", parse("f1,f2,f3,A", 3, 1)); // Ok([A])
}

关于rust - 在迭代器上使用 count() -> Result<usize> 函数的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46126772/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com