One way to approach this functionally would be something like this:
let my_2d_vector: Vec<Vec<u64>> = vec![vec![1, 4, 3], vec![3, 3, 3]];
let max_in_each_col =
my_2d_vector
.iter()
.skip(1)
.fold(my_2d_vector[0].clone(), |mut maxes, row| {
maxes
.iter_mut()
.zip(row.iter())
.for_each(|(m, col)| *m = std::cmp::max(*m, *col));
maxes
});
println!("{:?}", max_in_each_col); // [3, 4, 3]
However, it's a misconception that loops aren't idiomatic Rust. You may find that the above isn't all that readable, and rustfmt formats it into 11 lines. Whereas using loops, although the logic is exactly the same, you get this
let my_2d_vector: Vec<Vec<u64>> = vec![vec![1, 4, 3], vec![3, 3, 3]];
let mut max_in_each_col = my_2d_vector[0].clone();
for row in &my_2d_vector[1..] {
for (m, col) in max_in_each_col.iter_mut().zip(row.iter()) {
*m = std::cmp::max(*m, *col);
}
}
println!("{:?}", max_in_each_col); // [3, 4, 3]
in only 6 lines and very readably.