Non-contiguous slicing

I am trying to figure out the easiest way to do the equivalent of the following numpy code:

import numpy as np                                                     
M = np.arange(16).reshape(4, 4)                                        
M[:,[1, 3]]                                                            
>>array([[ 1,  3],
         [ 5,  7],
         [ 9, 11],
         [13, 15]])

I am fine with the slicing result being a new allocation, rather than a view into the original M, but I would like to avoid additional allocations on top of that. Of course, it is possible to create such a submatrix using from_columns or from_fn. The former however requires that I do intermediate allocations (creating a Vec of columns, just so that I can fulfill the &[Column] type requirement) and from_fn feels very unergonomic in this case. Is there a better way?

PS After some thought I figure that an additional allocation is also necessary in the numpy example, since the index array is dynamic. At which point it becomes almost equivalent with from_columns. I am still posting this because I may get some good insights.

Hi!

For zero-allocation, zero-copy, non-contiguous slicing, you can use the slicing methods that include a stride. See the slicing with step item from the user guide.

Alternatively, you can use .select_columns which will construct a matrix with the columns you want without any allocation other than the result matrix.

Here is some code that shows both approaches (you can run this on the playground if you want):

fn main() {
    let mat = DMatrix::from_fn(4, 4, |i, j| i * 4 + j);
    println!("Original matrix: {}", mat);
    
    // View-based approach.
    let view = mat.columns_with_step(1, 2, 1);
    println!("Zero-allocation matrix view: {}", view);
    
    // Column-selection approach.
    let submatrix = mat.select_columns([1, 3].into_iter());
    println!("Submatrix with allocation: {}", submatrix);
}

Output:

Original matrix: 
  ┌             ┐
  │  0  1  2  3 │
  │  4  5  6  7 │
  │  8  9 10 11 │
  │ 12 13 14 15 │
  └             ┘


Zero-allocation matrix view: 
  ┌       ┐
  │  1  3 │
  │  5  7 │
  │  9 11 │
  │ 13 15 │
  └       ┘


Submatrix with allocation: 
  ┌       ┐
  │  1  3 │
  │  5  7 │
  │  9 11 │
  │ 13 15 │
  └       ┘

Great, the latter is exactly what I need, thank you.

As a side question, select_columns, like many other items, lack documentation comments on the web documentation. When I view source, I can see the comment /// Creates a new matrix by extracting the given set of columns from 'self'. Where do all those comments go when rendering the html? When viewing the online documentation it appears like an undocumented blob of functions (aside from the module-level docs, which do show). Am I viewing the docs wrong or where is the issue?

Where do all those comments go when rendering the html? When viewing the online documentation it appears like an undocumented blob of functions (aside from the module-level docs, which do show). Am I viewing the docs wrong or where is the issue?

I believe rustdoc collapses all the comments by default. You need to click on the grey [+] button on the left of the function signature, just before the pub keyword:

Or you can press the [+] on the top-right of the HTML page (just before the [src] to expand/collapse every comment: