Чтение строк парами из стандартного ввода в rust

Мои входные данные структурированы следующим образом:

label_1
value_1
label_2
value_2
...

И моя конечная цель — прочитать эти данные в HashMap

Мой текущий рабочий подход заключается в том, чтобы поместить четные и нечетные строки в два отдельных вектора, а затем прочитать из обоих векторов, чтобы добавить в Hashmap.

use std::io;
use std::io::prelude::*;
use std::collections::HashMap;

fn main() {
    
    let mut labels: Vec<String> = Vec::new();
    let mut values: Vec<String> = Vec::new();
     
    let stdin = io::stdin();

    /* Read lines piped from stdin*/
    for (i, line) in stdin.lock().lines().enumerate() {
    
        if i % 2 == 0 {
            /* store labels (even lines) in labels vector */
            labels.push(line.unwrap());

        } else {
            /* Store values (odd lines) in values vector */
            values.push(line.unwrap());
        }
    }

    println!("number of labels: {}", labels.len());
    println!("number of values: {}", values.len());
    


    /* Zip labels and values into one iterator */
    let double_iter = labels.iter().zip(values.iter());

    /* insert (label: value) pairs into hashmap */
    let mut records: HashMap<&String, &String> = HashMap::new();
    for (label, value) in double_iter {
        records.insert(label, value);
    }
}

Я хотел бы спросить, как добиться этого результата, не проходя промежуточный шаг с векторами?

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
0
1 905
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Как насчет:

fn main() {
    let lines = vec![1,2,3,4,5,6];
    let mut records = std::collections::HashMap::new();

    for i in (0..lines.len()).step_by(2) {
        // make sure the `i+1` is existed
        println!("{}{}", lines[i], lines[i + 1]);
        records.insert(lines[i], lines[i + 1]);
    }
}

Если у вас уже есть вектор, вы можете вместо него использовать .chunks(2).

Lambda Fairy 14.12.2020 05:51

Вы можете вручную продвигать итератор с помощью .next()

use std::io;
use std::io::prelude::*;
use std::collections::HashMap;

fn main() {
    let stdin = io::stdin();
    let mut lines = stdin.lock().lines();
    let mut records = HashMap::new();

    while let Some(label) = lines.next() {
        let value = lines.next().expect("No value for label");
        records.insert(label.unwrap(), value.unwrap());
    }
}

Детская площадка

Ответ принят как подходящий

Вы можете использовать .tuples() из ящика itertools:

use itertools::Itertools;
use std::io::{stdin, BufRead};

fn main() {
    for (label, value) in stdin().lock().lines().tuples() {
        println!("{}: {}", label.unwrap(), value.unwrap());
    }
}

Смотрите также:

  • Этот ответ на тему «Есть ли эквиваленты slice::chunks/windows для итераторов для циклического перебора пар, троек и т. д.?»

Обратите внимание, что это молча терпит неудачу, когда есть непарная строка, в отличие от следующего ответа.

Lambda Fairy 14.12.2020 22:26

Другие вопросы по теме