地图闭合求和问题

Issue with summing over map closure

提问人:thefrollickingnerd 提问时间:11/7/2023 更新时间:11/7/2023 访问量:47

问:

我正在研究 AoC 来学习 Rust,并一直在尝试根据我看到的更有经验的 Rust 程序员编写的内容拼凑出一个解决方案。 下面似乎完全编译,除了我对 .sum() 有疑问。编译器指出,该状态更改为在求和运算之前。Iterator::ItemResult<usize, _>

我不知道我怎么会不使用结果类型。据我所知,sum 适用于迭代器,但它不认为结果类型是迭代器?get_priority

fn main() {
    
    let data = fs::read_to_string("data/data.txt").expect("File should exist");
    let lines = data.lines(); // this is an iterator of lines (type &str)

    let result: usize = lines.map(|rucksack| {
        let (cmprt1, cmprt2) = rucksack.split_at(rucksack.len() / 2);
        let cmprt1: ByteSet = cmprt1.into();
        let cmprt2: ByteSet = cmprt2.into();
        let dup = cmprt1.intersection(cmprt2).first().ok_or("Error finding intersection")?;
        Ok(get_priorty(dup)?)
    }).sum();    
    println!("{}", result)
}

fn get_priorty(letter: u8) -> Result<usize, Box<dyn Error>>{
    match letter {
        b'a'..=b'z' => Ok(1 - (letter + b'a') as usize),
        b'A'..=b'Z' => Ok(27 - (letter + b'A') as usize),
        _ => Err("Unexpected character in rucksack".into())
    }
}

错误消息

10   |       let result: usize = lines.map(|rucksack| {
     |  _______________________________^
11   | |         let (cmprt1, cmprt2) = rucksack.split_at(rucksack.len() / 2);
12   | |         let cmprt1: ByteSet = cmprt1.into();
13   | |         let cmprt2: ByteSet = cmprt2.into();
14   | |         let dup = cmprt1.intersection(cmprt2).first().ok_or("Error finding intersection")?;
15   | |         Ok(get_priorty(dup)?)
16   | |     }).sum();    
     | |______^ `Iterator::Item` changed to `Result<usize, _>` here
note: required by a bound in `std::iter::Iterator::sum`
Rust 迭代器 闭包

评论

0赞 Igor Artamonov 11/7/2023
map返回 for 项目类型 ,因为这是您返回的 。你可以把它变成一个像这样的向量,但是由于你想聚合它,你必须再次迭代它(例如)。我不确定你是否同意后者。希望它有助于获得一个想法,并希望其他人可以建议如何在不重复值的情况下实现它。IteratorResult<usize, _>Ok(..)collect.collect::<Result<Vec<usize>, _>>()?.collect::<Result<Vec<usize>, _>>()?.iter().sum()
0赞 thefrollickingnerd 11/7/2023
这仍然为我带来错误,导致函数出现编译错误,不返回结果。也许你可以解释为什么这个人的解决方案(我主要是从中复制的)不需要这些额外的步骤 github.com/niklasha/adventofcode2022/blob/main/src/day03.rs?

答:

4赞 cdhowie 11/7/2023 #1

由于映射函数是易错的,因此需要一种错误聚合的方法。您可以使用 Iterator::try_fold 来执行此操作。在你的情况下,而不是你会做 ,这将返回 .如果映射函数返回 ,则将传播该错误,否则它将返回总和。.sum().try_fold(0, |a, b| a + b)Result<usize, Box<dyn Error>>Errtry_foldOk

2赞 Jmb 11/7/2023 #2

对类型的项目求和时,会得到相同类型的结果。但是在这里,您尝试将结果强制为普通.您需要:Result<usize, E>usize

  • 提供正确的类型let result: Result<usize, Box<dyn Error>> = lines.map(|rucksack| { … }).sum();
  • 删除类型注释,让编译器推断出正确的类型:let result = lines.map(|rucksack| { … }).sum();
  • 或者处理错误:let result: usize = lines.map(|rucksack| { … }).sum().unwrap();

评论

0赞 cdhowie 11/8/2023
实现 的 TIL 。ResultSum