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

shstlldc  于 2022-12-19  发布在  其他
关注(0)|答案(2)|浏览(176)

所以我有一个Vec<Vec<T>>,其中第一个向量按一天中的小时分组,内部向量按一周中的天分组,我想把向量转置,先按天,再按小时,在Rust中有简单的方法吗?
编辑:我的意思是,我知道如何使用2个for循环,但有没有更聪明/更短的方法来实现它的功能

ee7vknir

ee7vknir1#

可以使用一些迭代器:

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

Playground

sy5wg1nm

sy5wg1nm2#

问题是 “我知道如何用两个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
}

有人可能会使它比我更“功能化”,但这已经有点难读了,尽我所能尝试。

相关问题