如何将Vec<Vec<f64>>的元素相加,得到一个Vec<f64>?

3
我正在寻找一种“生疏”的方法,将Vec<Vec>累加到一个Vec中,使得每个内部Vec的第1个元素相加,每个Vec的第2个元素相加等等,然后将结果收集到一个Vec中。如果我只使用sum()、fold()或accumulate(),我相信我会将整个第1个Vec的元素相加成为单个元素,而不是包含在2D Vec中的每个内部Vec的第1个元素。
pub fn main() {
    let v1 = vec![1.1, 2.2, 3.3];
    let vv = vec![v1; 3];
    let desired_result = vec![3.3, 6.6, 9.9];
}

我曾经考虑过使用vv.iter().flatten(),结合step_by(innerVec.len()),但这看起来很笨拙。 - Matthew Pittenger
你可否通过列而不是行的方式构建原始的 Vec<Vec<_>>?也许尝试使用 ndarray 库? - PitaJ
很遗憾,我将以Vec<Vec<_>>的形式接收我的数据,我无法控制接收数据的格式。 - Matthew Pittenger
数据从哪里来?如果你是从某个输入反序列化它,ndarray支持serde - PitaJ
共享内存IPC。 - Matthew Pittenger
这两个维度中有一个是常数吗? - PitaJ
3个回答

5
有时在Rust中很容易忘记存在命令式方法,并且是一种简单的解决方案。
let mut sums = vec![0.0; vv[0].len()];
for v in vv {
    for (i, x) in v.into_iter().enumerate() {
        sums[i] += x;
    }
}

哇,你说得对。很容易忘记。 - Matthew Pittenger
如果没有很快出现的功能性解决方案,我会将其标记为答案。 - Matthew Pittenger
谢谢您的回答,这是最佳解决方案,因为我需要它尽可能地高效,因为它在我的程序的主循环中。 - Matthew Pittenger

1

虽然我更喜欢@orlp的解决方案,但如果你非常想以最高效的方式完成此操作,可以按照以下方式进行:

let v1 = vec![1.1, 2.2, 3.3];
let vv = vec![v1; 3];
let sums = vec![0.0; vv[0].len()];
let summed = vv.into_iter().fold(sums, |mut sums, v| {
    v.into_iter().enumerate().for_each(|(i, x)| sums[i] += x);
    sums
});

0

如果事先知道内部向量的大小(或从vv向量中的第一个出现获取),则可以使用范围迭代器:

pub fn main() {
    let v1 = vec![1.1, 2.2, 3.3];
    let v1_len = v1.len();
    let vv = vec![v1; 3];
    let res: Vec<f64> = (0..v1_len)
        .map(|i| vv.iter().map(|v| v.get(i).unwrap()).sum())
        .collect();
    println!("{res:?}");
}

游乐场


我想指出的是,如果你关心性能,那么这个程序的内存访问模式比我的答案要差得多。 - orlp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接