ndarray rust, change values of a slice - rust

In python's numpy given an array
a = np.zeros((10,10,2))
I could modify values of the array corresponding to a slice 4:6,: as such:
a[4:6,:] = [0,255]
In rust: given a ndarray from the ndarray package, i can slice
let mut img = Array3::<u8>::zeros((10,10,2));
let slice = img.slice_mut(s![4..6,..,..]);
But what is the idiomatic way of changing the values of that slice, by broadcasting the subarray corresponding to the last axis i.e. [0,255]?

through other means i found answer and im posting it here. One needs to combine slice_mut with method .assign(&stuff to broadcast)
let mut img = Array3::<u8>::zeros((10,10,2));
let arr = Array::ones(2);
img.slice_mut(s![4..6usize,..,..]).assign(&arr);

Related

How do I map a range?

I am trying to build objects for every element in a range n, so I at the end have a slice of objects.
Cannot seem to figure out the right way, though. Tried:
[0..n].map(convert_int_to_object)
Square brackets [] denote arrays in Rust; a..b or (a..b) denotes a range. So to create an iterator over the range, what you're looking for is:
(0..n).map(convert_int_to_object)
This creates an iterator, but you will need to collect all the new objects into a collection such as a Vec. For example:
fn my_fun(n: i32) -> Vec<MyStruct> {
(0..n).map(convert_int_to_object).collect()
}
You asked for a slice, but you are creating new objects (allocation) so you need to use a Vec because it owns the new objects. You can get a slice from a vector v with &v or v.as_slice().
let v = my_fun(10);
let slice = v.as_slice();

Slicing a `DMatrix` and inserting the elements of that sub-matrix into a new matrix in Rust?

I have a function that takes in a 2-D DMatrix, x as a parameter, operates on slices of x and takes the output of the operation and inserts it into a new output matrix. What I have so far, with code and pseuod-code:
use nalgebra::DMatrix; // 0.31.1
fn rolling_function(x: DMatrix<f64>) -> DMatrix<f64> {
let nrows = x.shape().0;
let ncols = x.shape().1;
let mut out = DMatrix::from_element(nrows, ncols, 0.); // initialize x with zeros
let mut y: DMatrix<f64>;
let mut tmp_arr: DMatrix<f64>;
for i in 0..nrows {
//pseudo-code part
tmp_arr = x[0..i; all_cols]; // how do I take slices of x here?
y = my_func(&tmp_arr); // Some function that operates on &DMatrix<f64> and returns a DMatrix<f64>
out[i; all_cols] = y; // how do I overwrite parts of out here?
}
return out;
}
The issue is, I want to take a slice of x using something like x[0..i; all_cols], which would only take elements of x up to i, and all columns of x. Then I want to write y, which is a ncols by 1 DMatrix, into out at the i'th element.
What is the best way to do this using Rust and nalgebra syntax?

How to convert range to slice in rust?

I want to create a slice of numbers within certain range in Rust. However, the following syntax does not seem to work, as the output is a slice of length 1, composed of a Range object.
let count = 10;
let slice = [0..count/2];
What's the proper way to create a slice in Rust from a range?
You cannot create a slice directly from a range (unless you know an upper bound to the number of elements at compile time, in which case you can use an array), you have to use Vec:
let vec = Vec::from_iter(0..count/2);
let slice = vec.as_slice();

How is it possible to consume two arrays at the same time while iterating them with zip?

How is it possible to consume two arrays at the same time? zip will only give references while I need the actual objects to add them in a map.
let array1 : &[String] = &["abc".to_string(),"bcd".to_string()]
let array2 : &[String] = &["bcd".to_string(),"abc".to_string()]
for a,b in array1.into_iter().zip(array2.into_iter()){
map.insert(a,b); // Doesn't work because a and b are &String instead of String
}
Your variables array1 and array2 are not arrays, they are immutable references to slices, similar but not the same. You cannot take ownership of data hidden behind an immutable reference. As such, .into_iter() will yield &Strings, the fault is not due to .zip().
What you want is something like this:
let array1 = ["abc".to_string(), "bcd".to_string()];
let array2 = ["bcd".to_string(), "abc".to_string()];
for (a, b) in array1.into_iter().zip(array2.into_iter()) {
map.insert(a, b);
}

How to make a vector of received size?

I have a vector data with size unknown at compile time. I want to create a new vector of the exact that size. These variants don't work:
let size = data.len();
let mut try1: Vec<u32> = vec![0 .. size]; //ah, you need compile-time constant
let mut try2: Vec<u32> = Vec::new(size); //ah, there is no constructors with arguments
I'm a bit frustrated - there is no any information in Rust API, book, reference or rustbyexample.com about how to do such simple base task with vector.
This solution works but I don't think it is good to do so, it is strange to generate elements one by one and I don't have need in any exact values of elements:
let mut temp: Vec<u32> = range(0u32, data.len() as u32).collect();
The recommended way of doing this is in fact to form an iterator and collect it to a vector. What you want is not precisely clear, however; if you want [0, 1, 2, …, size - 1], you would create a range and collect it to a vector:
let x = (0..size).collect::<Vec<_>>();
(range(0, size) is better written (0..size) now; the range function will be disappearing from the prelude soon.)
If you wish a vector of zeroes, you would instead write it thus:
let x = std::iter::repeat(0).take(size).collect::<Vec<_>>();
If you merely want to preallocate the appropriate amount of space but not push values onto the vector, Vec::with_capacity(capacity) is what you want.
You should also consider whether you need it to be a vector or whether you can work directly with the iterator.
You can use Vec::with_capacity() constructor followed by an unsafe set_len() call:
let n = 128;
let v: Vec<u32> = Vec::with_capacity(n);
unsafe { v.set_len(n); }
v[12] = 64; // won't panic
This way the vector will "extend" over the uninitialized memory. If you're going to use it as a buffer it is a valid approach, as long as the type of elements is Copy (primitives are ok, but it will break horribly if the type has a destructor).

Resources