Search code examples
multidimensional-arrayvectorrustfunctional-programmingiterator

Rust: Idomatic way to iterate over columns of a 2d vector


I am new to Rust and wanted to know whats the idomatic way to iterate over columns on a 2d vector. I know how to do it for a rows, for example finding maximum for each row as below

let my_2d_vector: Vec<Vec<u64>> = vec![];
let max_in_each_rows = my_2d_vector.iter()
   .map(|&row| row.iter().max())
   .collect::<Vec<64>>();

How do I find maximum for each column without using loops?


Solution

  • 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.