在2D矢量中读取时如何消除临时矢量?

时间:2016-07-15 02:43:04

标签: vector rust

我有这个代码用于在2D矢量中读取。有没有办法消除temp_vec的需要?

let mut vec_size: usize = 3;
let mut vec = vec![vec![0; vec_size]; vec_size];   
for i in 0..vec_size{
    input = String::new();
    io::stdin().read_line(&mut input).expect("Failed to read");
    let temp_vec: Vec<i32> = input
             .split_whitespace()
             .map(|s| s.parse().unwrap())
             .collect();
    for j in 0..temp_vec.len(){
        vec[i][j] = temp_vec[j];
    }
}

2 个答案:

答案 0 :(得分:3)

我删除collect()调用,最终得到一个迭代器,你可以enumerate()并传递给for循环:

use std::io;

fn main() {
    let vec_size: usize = 3;
    let mut vec = vec![vec![0; vec_size]; vec_size];   
    let mut input = String::new();
    for i in 0..vec_size {
        input.clear();
        io::stdin().read_line(&mut input).expect("Failed to read");
        let numbers = input
            .split_whitespace()
            .map(|s| s.parse().unwrap());
        for (j, x) in numbers.enumerate() {
            vec[i][j] = x;
        }
    }
}

此代码还调用clear()来清除输入缓冲区而不是分配新的字符串,因此它只需要一个额外的分配(如果你正在阅读很多小矩阵,你可能会从中受益)。

(关于你的代码的旁注:如果可以的话,使用.iter().enumerate()比迭代矢量索引更好)

在写这个答案时,我误解了原来的问题,认为有一个堆栈分配的矩阵:

const VEC_SIZE: usize = 3;
let mut vec = [[0; VEC_SIZE]; VEC_SIZE];

如果是这种情况,我会推荐我的解决方案,但由于它是Vec<Vec<i32>>,我推荐@ Shepmaster's,因为它更具惯用性

答案 1 :(得分:1)

将标准输入的行映射为行,然后将每行中的数字映射为列。

use std::io;
use std::io::prelude::*;

const SIZE: usize = 3;

fn main() {
    let stdin = io::stdin();
    let vec: Vec<Vec<i32>> = stdin.lock()
        .lines()
        .take(SIZE)
        .map(|line| {
            let line = line.expect("Unable to read line");
            line.split_whitespace()
                .take(SIZE)
                .map(|s| s.parse().expect("Enable to parse number"))
                .collect()
        })
        .collect();

    println!("{:?}", vec);
}

或者如果你不在乎恐慌:

use std::io;
use std::io::prelude::*;
use std::error::Error;

const SIZE: usize = 3;

fn main() {
    let stdin = io::stdin();
    let vec: Result<Vec<Vec<i32>>, _> = stdin.lock()
        .lines()
        .take(SIZE)
        .map(|line| {
            line.map_err(|e| Box::new(e) as Box<Error>)
                .and_then(|line| {
                    line.split_whitespace()
                        .take(SIZE)
                        .map(|s| s.parse().map_err(|e| Box::new(e) as Box<Error>))
                        .collect()
                })
        })
        .collect();

    println!("{:?}", vec);
}

解决评论中的问题:

  

您的代码会进行2n + 1次分配(如果有人在寻找性能,这很重要

目前还不清楚N是什么,但最多应分配3个向量,每个向量中有3个项目。 take适配器将覆盖size_hint以最多3,然后collect将在构建每个Vec时使用该提示。

  

对矩阵使用嵌套的Vec是一个反模式。

当然,但这就是原始代码所做的。

  

你“打破”stdin - 在调用lock().lines()

后你无法可靠地使用它

我不确定你的意思。我能够在定义stdin.read(&mut[0,0,0]).expect("Unable to read more")的代码块之后添加let vec,表明它可以被使用。

如果无法使用stdin存在问题,您可以通过将锁定范围限定为更早结束的块来修复它。