如何在 Rust 中转置向量的向量?

问题描述 投票:0回答:4

所以我有一个

Vec<Vec<T>>
,其中第一个向量按一天中的小时进行分组,内部向量按一周中的天进行分组。我想以某种方式转置向量,先按天,然后按小时。 Rust 有没有简单的方法?

编辑:我的意思是,我知道如何用 2 个 for 循环来完成它,但是有没有更智能/更短的方法来实现它的功能

vector rust
4个回答
20
投票

您可以使用一些迭代器:

fn transpose<T>(v: Vec<Vec<T>>) -> Vec<Vec<T>>
where
    T: Clone,
{
    assert!(!v.is_empty());
    (0..v[0].len())
        .map(|i| v.iter().map(|inner| inner[i].clone()).collect::<Vec<T>>())
        .collect()
}

正如

user4815162342
评论,这是一个没有
Clone
的版本:

fn transpose2<T>(v: Vec<Vec<T>>) -> Vec<Vec<T>> {
    assert!(!v.is_empty());
    let len = v[0].len();
    let mut iters: Vec<_> = v.into_iter().map(|n| n.into_iter()).collect();
    (0..len)
        .map(|_| {
            iters
                .iter_mut()
                .map(|n| n.next().unwrap())
                .collect::<Vec<T>>()
        })
        .collect()
}

游乐场


1
投票

问题说“我知道如何用2个for循环来做到这一点,但是有没有一种更智能/更短的方法来实现它的功能”,但这可能是标题的最佳答案。这是一个两

for
循环解决方案,可以避免
T: Clone
并避免为迭代器分配暂存
Vec

fn transpose<T>(original: Vec<Vec<T>>) -> Vec<Vec<T>> {
    assert!(!original.is_empty());
    let mut transposed = (0..original[0].len()).map(|_| vec![]).collect::<Vec<_>>();

    for original_row in original {
        for (item, transposed_row) in original_row.into_iter().zip(&mut transposed) {
            transposed_row.push(item);
        }
    }

    transposed
}

也许有人可以让它比我更“实用”,但这已经有点难以阅读,尽我所能。


0
投票

这是一种方法

let v = vec![vec![1,2,3,4], vec![5,6,7,8]];
let rows = v.len();
let cols = v[0].len();

let transposed: Vec<Vec<_>> = (0..cols).map(|col| {
    (0..rows)
        .map(|row| v[row][col])
        .collect()
}).collect();

0
投票

以下方法展示了如果数据类型不具有复制特征并且工作正常,如何避免克隆(这意味着我们重用原始数据并将它们构造成新的结构,而不是像前面的答案所示那样制作副本)以功能性的方式。

fn main() {
    let x = vec![
        vec![String::from("a"), String::from("b"), String::from("c")],
        vec![String::from("d"), String::from("e"), String::from("f")]
    ];
    let n = 3;
    
    // take the iterators out 
    let mut iters = x
        .into_iter()
        .map(|u| u.into_iter())
        .collect::<Vec<_>>();
    
    // grab elements from iterators and compose the column vector
    let transpose = (0..n)
        .map(
            |_| iters
                .iter_mut()
                .map(|y| y.next().unwrap())
                .collect::<Vec<_>>()
        )
        .collect::<Vec<_>>();
    
    println!("{:?}", transpose);
}
© www.soinside.com 2019 - 2024. All rights reserved.