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

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

问题描述

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

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 没有t 有一个 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()返回).

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天全站免登陆