如何使用同一个迭代器两次,一次用于计数,一次用于迭代? [英] How to use the same iterator twice, once for counting and once for iteration?

查看:522
本文介绍了如何使用同一个迭代器两次,一次用于计数,一次用于迭代?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎在计数时消耗了迭代器.如何使用相同的迭代器进行计数然后对其进行迭代?

It seems that an iterator is consumed when counting. How can I use the same iterator for counting and then iterate on it?

我正在尝试计算文件中的行数,然后打印它们.我能够读取文件内容,能够计算行数,但是然后我就无法像内部游标位于迭代器末尾那样对行进行迭代.

I'm trying to count the lines in a file and then print them. I am able to read the file content, I'm able to count the lines count, but then I'm no longer able to iterate over the lines as if the internal cursor was at the end of the iterator.

use std::fs::File;
use std::io::prelude::*;

fn main() {
    let log_file_name = "/home/myuser/test.log";
    let mut log_file = File::open(log_file_name).unwrap();
    let mut log_content: String = String::from("");
    //Reads the log file.
    log_file.read_to_string(&mut log_content).unwrap();
    //Gets all the lines in a Lines struct.
    let mut lines = log_content.lines();
    //Uses by_ref() in order to not take ownership
    let count = lines.by_ref().count();
    println!("{} lines", count); //Prints the count
                                 //Doesn't enter in the loop
    for value in lines {
        println!("{}", value);
    }
}

Iterator 没有reset方法,但是内部游标似乎在计数之后的迭代器的末尾.是否必须创建一个新的 Lines 再次调用log_content.lines()还是可以重置内部光标?

Iterator doesn't have a reset method, but it seems the internal cursor is at the end of the iterator after the count. Is it mandatory to create a new Lines by calling log_content.lines() again or can I reset the internal cursor?

现在,我发现的解决方法是创建一个新的迭代器:

For now, the workaround that I found is create a new iterator:

use std::fs::File;
use std::io::prelude::*;

fn main() {
    let log_file_name = "/home/myuser/test.log";
    let mut log_file = File::open(log_file_name).unwrap();
    let mut log_content: String = String::from("");
    //Reads the log file.
    log_file.read_to_string(&mut log_content).unwrap();
    //Counts all and consume the iterator
    let count = log_content.lines().count();
    println!("{} lines", count);
    //Creates a pretty new iterator
    let lines = log_content.lines();
    for value in lines {
        println!("{}", value);
    }
}

推荐答案

调用count会消耗迭代器,因为它实际上会迭代直到完成为止(即next()返回None).

Calling count consumes the iterator, because it actually iterates until it is done (i.e. next() returns None).

您可以通过使用by_ref来防止消耗迭代器,但是迭代器仍会被驱动完成(by_ref实际上只是将可变引用返回给迭代器,并且Iterator也实现了可变引用: impl<'a, I> Iterator for &'a mut I).

You can prevent consuming the iterator by using by_ref, but the iterator is still driven to its completion (by_ref actually just returns the mutable reference to the iterator, and Iterator is also implemented for the mutable reference: impl<'a, I> Iterator for &'a mut I).

如果迭代器包含要在完成后重用的其他状态,但在这种情况下不是这样,这仍然很有用.

This still can be useful if the iterator contains other state you want to reuse after it is done, but not in this case.

您可以简单地尝试分叉迭代器(如果它们没有副作用,它们通常会实现Clone),尽管在这种情况下,重新创建同样好(大多数情况下,创建迭代器很便宜;真正的通常只有在通过直接或间接调用next进行驱动时才能完成工作.

You could simply try forking the iterator (they often implement Clone if they don't have side effects), although in this case recreating it is just as good (most of the time creating an iterator is cheap; the real work is usually only done when you drive it by calling next directly or indirectly).

因此,不能,(在这种情况下)您无法将其重置,是的,您需要创建一个新的(或在使用它之前对其进行克隆).

So no, (in this case) you can't reset it, and yes, you need to create a new one (or clone it before using it).

这篇关于如何使用同一个迭代器两次,一次用于计数,一次用于迭代?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆