首页 > 解决方案 > Calamine crate (Rust) 只读取 xlsx 文件的第一行,如何解决?

问题描述

我对 Rust 作为一种爱好产生了兴趣(我是一个业余程序员,我使用 python 和 C++ 来自动化工作中的事情),我目前正在尝试通过移植一些用于数据分析的 python 代码来练习rust,但事实证明它对我来说非常困难,因为我在这方面完全是个菜鸟,而且大多数资源和文档更倾向于中级和高级 rust 用户(至少对于数据科学而言)。

我正在尝试使用炉甘石板条箱将 xlsx 文件加载到 Vec 中,但是在 for 循环中使用迭代器的 .next() 方法时只解析第一行,所以我显然做错了。作为可能有帮助的额外信息,xlsx 文件由 23851 行和 28 列组成,实际数据(不考虑标题,不是被读取的)从位置 A3 开始。

    let range = excel
        .worksheet_range("Sheet0")
        .ok_or(calamine::Error::Msg("Cannot find Sheet0"))??;
    
    let start = range.start().unwrap();
    let end = range.end().unwrap();
    
    // First cell to be read starts at 'A3', theres probably a better way to do this
    let range = range.range((start.0 + 2, start.1), end);

    println!("Start: {:?} - End: {:?}", range.start(), range.end());

    let mut iter = RangeDeserializerBuilder::new().has_headers(false).from_range::<_, mr::RawMR>(&range)?;

    let mut df: Vec<mr::RawMR> = Vec::new();

    for result in iter.next() {
        match result {
            Ok(row) => { df.push(row); }
            Err(e) => println!("Error: {}", e), };
    }
    
    // This prints 'Size: 1', I was expecting the total number of rows
    println!("Size: {:?}", df.len());

此代码仅设法读取 excel 文件的第一行,因此 vec 仅包含第一行。

任何帮助是极大的赞赏。

提前致谢

标签: rustxlsx

解决方案


我在您的代码中看到的错误是您如何对待迭代器。next()每次调用都会返回一个元素。要获得下一个元素,必须再调用一次。

循环

for result in iter.next() {
    match result {
        Ok(row) => { df.push(row); }
        Err(e) => println!("Error: {}", e), };
}

只会产生一个结果,因为收到的列表for in是来自的返回值iter.next()

如果您仅将其替换为迭代器或while let Some()=iter.next().

for result in iter {

  ...
}

for ... in将在迭代器上运行,直到 next 返回 None,但你不应该调用它。

在替代方案while let中,每次循环重新启动时都会执行分配。因此next()需要

while let Some(result) = iter.next() {
  ...
}

您应该能够遍历整个空间。


推荐阅读