Search code examples
rustfunctional-programming

sum up member variables from an array with reduce


With struct Var defined like this:

pub struct Var {
    val: i32,
}

I hope to add up all val from an array of Vars:

pub struct Var {
    val: i32,
}

fn main() {
    let var0 = Var { val: 0 };
    let var1 = Var { val: 1 };

    let array = [var0, var1];

    let sum = array.into_iter().reduce(|x, y| Var { val: x.val + y.val });
}

The code looks redundant to me as for every addition in reduce, a new Var was created. I hope to avoid such waste by adding only val yet it is impossible:

let sum = array.into_iter().reduce(|x, y| x.val + y.val);

expected struct Var, found i32

The other way to fix it would be to fetch val from all var and then sum them up, which doesn't look too smart either:

let vals: Vec<i32> = array.into_iter().map(|var| var.val).collect();
let sum = vals.into_iter().reduce(|x, y| x + y);

Is there an elegant and efficient way to sum up all member variables from an array of struct?


Solution

  • You can chain iterators without needing to collect intermediate results:

    let sum = array.into_iter().map (|var| var.val).reduce(|x, y| x + y);
    

    Or better, you can use sum instead of reduce, and use iter instead of into_iter so that you won't destroy the original array:

    let sum = array.iter().map (|var| var.val).sum::<i32>();
    

    Another notable option is to use fold to combine the effects of map and sum in a single call:

    let sum = array.fold (0, |v, s| s + v.val);
    

    Note that reduce returns None for an empty array and Some (sum) for a non-empty array, the other solutions return 0 for an empty array and the bare sum otherwise.