gpt4 book ai didi

vector - 惯用地将空格分隔的字符串解析为不同类型元组的 Vec

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

我有一个结构 EnclosingObject其中包含一个 Vec 的字段的元组。我想实现 FromStr对于这个结构,EnclosingObject可以从具有以下结构的字符串中解析:<number of tuples> <tuple1 str1> <tuple1 str2> <tuple1 i32> <tuple2 str1> <tuple2 str2> ...

这是我到目前为止的想法(忽略无效元组数的情况):

use std::str::FromStr;
use std::num::ParseIntError;

#[derive(Debug)]
struct EnclosingObject{
tuples: Vec<(String, String, i32)>,
}

impl FromStr for EnclosingObject {
type Err = ParseIntError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let elems_vec = s.split_whitespace().collect::<Vec<_>>();
let mut elems = elems_vec.as_slice();

let num_tuples = elems[0].parse::<usize>()?;
elems = &elems[1..];
let mut tuples = Vec::with_capacity(num_tuples);
for chunk in elems.chunks(3).take(num_tuples){
tuples.push((chunk[0].into(),
chunk[1].into(),
chunk[2].parse::<i32>()?));
}

Ok(EnclosingObject{
tuples : tuples
})
}
}

fn main(){
println!("{:?}", EnclosingObject::from_str("3 a b 42 c d 32 e f 50"));
}

( playground )

正如预期的那样,对于一个有效的字符串,它会打印出:

Ok(EnclosingObject { tuples: [("a", "b", 42), ("c", "d", 32), ("e", "f", 50)] })

对于无效的字符串,例如“3 a b x c d 32 e f 50”:

Err(ParseIntError { kind: InvalidDigit })

我可以解析这个Vec吗?以更优雅/惯用的方式处理元组,例如使用迭代器?

我尝试了 map 的组合和 collect ,但问题在于错误处理:

let tuples = elems
.chunks(3)
.take(num_tuples)
.map(|chunk| (chunk[0].into(),
chunk[1].into(),
chunk[2].parse::<i32>()?))
.collect();

问号运算符似乎在这种情况下(在元组内)不起作用。所以我稍微改造了一下:

let tuples = try!(elems
.chunks(3)
.take(num_tuples)
.map(|chunk| {
let integer = chunk[2].parse::<i32>()?;
Ok((chunk[0].into(),
chunk[1].into(),
integer))})
.collect());

...这有效,但又显得有点麻烦。

最佳答案

The questionmark-operator seems not to work in this context (within the tuple).

问题是 ?返回 Err以防万一失败并且您没有返回 Ok在成功的情况下。如果你这样做,运算符(operator)工作得很好。除此之外,您还可以避免额外分配 Vec。通过对空格进行拆分的迭代器进行操作:

fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut elems = s.split_whitespace();

let num_tuples = elems.next().expect("error handling: count missing").parse()?;
let tuples: Vec<_> = elems
.by_ref()
.tuples()
.map(|(a, b, c)| Ok((a.into(), b.into(), c.parse()?)))
.take(num_tuples)
.collect::<Result<_, _>>()?;

if tuples.len() != num_tuples { panic!("error handling: too few") }
if elems.next().is_some() { panic!("error handling: too many") }

Ok(EnclosingObject { tuples })
}

我还使用了 Itertools 的 tuples自动将迭代器分组为元组并收集到 Result<Vec<_>, _> 中的方法.我减少了多余的 tuples: tuples在结构中,并为错误处理的其余部分添加了一些占位符。我删除了 Vec::with_capacity因为我相信 size_hinttake 设置会足够好。如果您不信任它,您仍然可以使用 with_capacity然后 extend带有迭代器的向量。

关于vector - 惯用地将空格分隔的字符串解析为不同类型元组的 Vec,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46958593/

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