2017-12-30 16 views
1

계산할 때 반복기가 사용 된 것으로 보입니다. 어떻게 같은 반복자를 세고 그것을 반복 할 수 있습니까?카운트 및 반복에 동일한 반복기를 사용하는 방법은 무엇입니까?

파일의 행을 계산 한 다음 인쇄하려고합니다. 파일 내용을 읽을 수 있지만 줄 수를 셀 수는 있지만 내부 커서가 반복자의 끝에있는 것처럼 더 이상 줄을 반복 할 수 없습니다.

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 방법을 가지고 있지 않지만, 내부 커서가 계산 후 반복자의 끝에 보인다. 다시 log_content.lines()으로 전화하여 새 Lines을 작성해야합니까? 아니면 내부 커서를 재설정 할 수 있습니까? 지금은

은, 내가 찾은 해결 방법은 새로운 반복자를 만드는 것입니다 :

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); 
    } 
} 

답변

3

count을 호출하면 실제로 반복 될 때까지 반복됩니다 (즉, next()None을 반환).

당신은 by_ref를 사용하여 반복자를 소모 방지 할 수 있지만, 반복자는 아직 완료 (by_ref 실제로 단지 반복자로 변경 가능한 참조를 반환하고, Iterator도 변경 가능한 참조 구현됩니다 impl<'a, I> Iterator for &'a mut I)로 구동된다.

반복자에 완료 후에 다시 사용할 다른 상태가 포함되어 있지만이 경우 유용하지 않을 수 있습니다.

이 경우 반복기를 만드는 것이 가장 좋습니다 (대부분 반복기를 만드는 것이 값 싸고 실제 작업은 효과가 있지만 반복 효과가없는 경우에는 종종 Clone을 구현합니다). 보통 직접 또는 간접적으로 next으로 전화하여 운전할 때만 수행됩니다.

아니요 (이 경우) 재설정 할 수 없으며 새 항목을 만들거나 사용하기 전에 복제해야합니다.

+0

답변 해 주셔서 감사합니다. 이터레이터를 복제하는 것에 대해서는 생각해 보았습니다 만,이 경우에는 새로운 iterator를 만드는 것과 같습니다. 나는 반복문에 비용 (for 또는 in count 중 하나)이 있음을 이해하지만, 반복 할 때만 비용이 들며 필요할 때만 반복한다. 그러나 다시 반복 할 수 없다면 새로운 반복자를 만들 것입니다. – AnthonyB

-4
과학이 조건 주어진 주어진 반복 계속 루프와 같은 것이 아니다의 반복자 컴퓨터에

그 만난다. 반복자 (iterates)는 반복되는 것을 말합니다. 일반적으로 주어진 데이터 세트를 통해 한 번만. 간단한 반복과는 다른 기능을 원한다면; 클래스를 정의하고 원하는 고객 동작을 제공하십시오. 그것이 OOP의 상속이 들어오는 곳입니다. 반복 할 언어가 무엇이든 관계없이 반복자 기본 동작은 원하는 기능 (예 : 데이터 시작으로 재설정)이 있는지 확인하기 위해 클래스 API를 검토해야합니다 당신이 사용하고 있습니다.

+0

답변을 주셔서 감사 합니다만, 녹이 클래스도 상속을 가지고 있지 않습니다, 단지 구조체가 있습니다. 이 경우에는'Iterator'라는 특성을 구현하는'Lines' 구조체가 있습니다. 그래서 값을 가리키는 내부 커서가 있고 반복자가 반복자를 반복하고 반복자가 내부 커서를 이동하여 다음 값을 가리킨다 고 가정합니다. 많은 언어에서 커서를 재설정 할 필요없이 계산할 수 있지만 Rust에서는 커서가 이동됩니다. 새로운 반복자를 만들거나 동일한 반복자를 사용할 수 있는지 여부는 모르겠습니다. – AnthonyB

+0

사실 그건 잘못되었습니다. Rust에서 반복자는 거의 모든면에서 for 루프와 동일합니다. 반복자는 for 루프와 거의 동일한 기계어 코드로 컴파일됩니다. [-] 가 반복 복제, 가 : - https://doc.rust-lang.org/book/second-edition/ch13-04-performance.html – StarSheriff

+0

FN주기 (자기) 자기가> 사이클 끝없이 반복자. None에서 중지하는 대신 반복기가 처음부터 다시 시작됩니다. 다시 반복 한 다음 처음부터 다시 시작합니다. 그리고 다시. 그리고 다시. 영원히. iterator가 정확히 무엇을해야하는지 반복자가 반복하는 것은 잘못이 아닙니다. 내 게시물의 첫 번째 줄을 읽으십시오. 반복자가 무언가를 한 번 이상 반복 할 수 있도록하려면 포함 된 기능을 사용하거나 직접 정의해야합니다. –

2

반복자는 반복 비용이 들기 때문에 일반적으로 두 번 반복 할 수 없습니다. str::lines의 경우, 각 반복은 줄의 다음 끝을 찾아야합니다. 이는 문자열을 반복하는 것을 의미합니다. 이것은 약간의 비용이 든다. 반복자는 나중에 재사용 할 수 있도록 해당 위치를 저장할 수 있다고 주장 할 수 있지만 비용은 훨씬 더 많이 듭니다. 일부 Iterator은 반복하는 데 더 많은 비용이 들기 때문에 실제로 두 번하고 싶지 않습니다.

그러나 대부분의 반복기는 쉽게 다시 생성 할 수 있습니다 (여기서 str::lines을 두 번째로 호출합니다) 또는 clone d가 될 수 있습니다. 어느 쪽의 방법으로 반복자를 재 작성해도, 2 개의 반복자는 일반적으로 완전히 독립하고 있습니다. 반복 처리하면, 두 번 가격을 지불하게됩니다.

특정 경우에, 문자열을 두 번 반복하는 것은 메모리에 들어 맞는 문자열이 단순히 계산 라인이 매우 비싼 작업이 될 때까지는 안된다. 이것이 사실이라고 믿는다면, 먼저 Lines::count으로 알고리즘을 작성하십시오. Lines의 주요 목표는 회선을 반복하는 것이므로 가능한 한 많이 최적화되지 않습니다.

+0

답변 해 주셔서 감사합니다. 반복기에 대한 반복에는 비용이 들지만 Stefan에 말했듯이 나는 필요한 경우에만 throuth를 반복합니다. 그래서이 경우 iterate를 선택하는 것이 좋습니다. 하지만 필자는 필연적으로 반복적으로 성능을 낭비하지 않기 위해 노력하고 있습니다. 그래서 제가 생각하기에 꽤 새로운 반복자를 만들 것입니다. – AnthonyB

관련 문제