How do I pass a Vec<Vec<i32>> to a function? - vector

Given a 2D vector of i32s:
let v = vec![
vec![1, 1, 1],
vec![0, 1, 0],
vec![0, 1, 0],
];
How can I pass it to a function to ultimately print its details? I tried:
fn printVector(vector: &[[i32]]) {
println!("Length{}", vector.len())
}

You may use a function which accepts a slice of T where T can also be referenced as a slice:
fn print_vector<T>(value: &[T])
where
T: AsRef<[i32]>,
{
for slice in value {
println!("{:?}", slice.as_ref())
}
}
playground
If you want to accept any type instead of just i32, you can also generalize this:
fn print_vector<T, D>(value: &[T])
where
T: AsRef<[D]>,
D: Debug,
{
for slice in value {
println!("{:?}", slice.as_ref())
}
}
playground

Since you're going to pass vectors to your function, the following code should work:
fn print_vector(vector: Vec<Vec<i32>>) {
println!("Length{}", vector.len())
}

You need to pass a slice of vectors - &[Vec<i32>], not a slice of slices:
fn print_vector(vector: &[Vec<i32>]) {
println!("Length {}", vector.len())
}
fn main() {
let v = vec![vec![1, 1, 1], vec![0, 1, 0], vec![0, 1, 0]];
print_vector(&v);
}
Playground

fn printVector(vector: &Vec<Vec<i32>>) {
println!("Length{}", vector.len())
}
let v = vec![
vec![1, 1, 1],
vec![0, 1, 0],
vec![0, 1, 0],
];
printVector(&v);
In this example, &Vec<Vec<i32> and &[Vec<i32>] are no different; maybe you want to change to this:
fn print_vector(vector: &[Vec<i32>]) {
for i in vector {
for j in i {
println!("{}", j)
}
}
}
let v = vec![
vec![1, 1, 1],
vec![0, 1, 0],
vec![0, 1, 0],
];
print_vector(&v);

Related

How to bulk insert into a vector in rust? [duplicate]

Is there any straightforward way to insert or replace multiple elements from &[T] and/or Vec<T> in the middle or at the beginning of a Vec in linear time?
I could only find std::vec::Vec::insert, but that's only for inserting a single element in O(n) time, so I obviously cannot call that in a loop.
I could do a split_off at that index, extend the new elements into the left half of the split, and then extend the second half into the first, but is there a better way?
As of Rust 1.21.0, Vec::splice is available and allows inserting at any point, including fully prepending:
let mut vec = vec![1, 5];
let slice = &[2, 3, 4];
vec.splice(1..1, slice.iter().cloned());
println!("{:?}", vec); // [1, 2, 3, 4, 5]
The docs state:
Note 4: This is optimal if:
The tail (elements in the vector after range) is empty
or replace_with yields fewer elements than range’s length
or the lower bound of its size_hint() is exact.
In this case, the lower bound of the slice's iterator should be exact, so it should perform one memory move.
splice is a bit more powerful in that it allows you to remove a range of values (the first argument), insert new values (the second argument), and optionally get the old values (the result of the call).
Replacing a set of items
let mut vec = vec![0, 1, 5];
let slice = &[2, 3, 4];
vec.splice(..2, slice.iter().cloned());
println!("{:?}", vec); // [2, 3, 4, 5]
Getting the previous values
let mut vec = vec![0, 1, 2, 3, 4];
let slice = &[9, 8, 7];
let old: Vec<_> = vec.splice(3.., slice.iter().cloned()).collect();
println!("{:?}", vec); // [0, 1, 2, 9, 8, 7]
println!("{:?}", old); // [3, 4]
Okay, there is no appropriate method in Vec interface (as I can see). But we can always implement the same thing ourselves.
memmove
When T is Copy, probably the most obvious way is to move the memory, like this:
fn push_all_at<T>(v: &mut Vec<T>, offset: usize, s: &[T]) where T: Copy {
match (v.len(), s.len()) {
(_, 0) => (),
(current_len, _) => {
v.reserve_exact(s.len());
unsafe {
v.set_len(current_len + s.len());
let to_move = current_len - offset;
let src = v.as_mut_ptr().offset(offset as isize);
if to_move > 0 {
let dst = src.offset(s.len() as isize);
std::ptr::copy_memory(dst, src, to_move);
}
std::ptr::copy_nonoverlapping_memory(src, s.as_ptr(), s.len());
}
},
}
}
shuffle
If T is not copy, but it implements Clone, we can append given slice to the end of the Vec, and move it to the required position using swaps in linear time:
fn push_all_at<T>(v: &mut Vec<T>, mut offset: usize, s: &[T]) where T: Clone + Default {
match (v.len(), s.len()) {
(_, 0) => (),
(0, _) => { v.push_all(s); },
(_, _) => {
assert!(offset <= v.len());
let pad = s.len() - ((v.len() - offset) % s.len());
v.extend(repeat(Default::default()).take(pad));
v.push_all(s);
let total = v.len();
while total - offset >= s.len() {
for i in 0 .. s.len() { v.swap(offset + i, total - s.len() + i); }
offset += s.len();
}
v.truncate(total - pad);
},
}
}
iterators concat
Maybe the best choice will be to not modify Vec at all. For example, if you are going to access the result via iterator, we can just build iterators chain from our chunks:
let v: &[usize] = &[0, 1, 2];
let s: &[usize] = &[3, 4, 5, 6];
let offset = 2;
let chain = v.iter().take(offset).chain(s.iter()).chain(v.iter().skip(offset));
let result: Vec<_> = chain.collect();
println!("Result: {:?}", result);
I was trying to prepend to a vector in rust and found this closed question that was linked here, (despite this question being both prepend and insert AND efficiency. I think my answer would be better as an answer for that other, more precises question because I can't attest to the efficiency), but the following code helped me prepend, (and the opposite.) [I'm sure that the other two answers are more efficient, but the way that I learn, I like having answers that can be cut-n-pasted with examples that demonstrate an application of the answer.]
pub trait Unshift<T> { fn unshift(&mut self, s: &[T]) -> (); }
pub trait UnshiftVec<T> { fn unshift_vec(&mut self, s: Vec<T>) -> (); }
pub trait UnshiftMemoryHog<T> { fn unshift_memory_hog(&mut self, s: Vec<T>) -> (); }
pub trait Shift<T> { fn shift(&mut self) -> (); }
pub trait ShiftN<T> { fn shift_n(&mut self, s: usize) -> (); }
impl<T: std::clone::Clone> ShiftN<T> for Vec<T> {
fn shift_n(&mut self, s: usize) -> ()
// where
// T: std::clone::Clone,
{
self.drain(0..s);
}
}
impl<T: std::clone::Clone> Shift<T> for Vec<T> {
fn shift(&mut self) -> ()
// where
// T: std::clone::Clone,
{
self.drain(0..1);
}
}
impl<T: std::clone::Clone> Unshift<T> for Vec<T> {
fn unshift(&mut self, s: &[T]) -> ()
// where
// T: std::clone::Clone,
{
self.splice(0..0, s.to_vec());
}
}
impl<T: std::clone::Clone> UnshiftVec<T> for Vec<T> {
fn unshift_vec(&mut self, s: Vec<T>) -> ()
where
T: std::clone::Clone,
{
self.splice(0..0, s);
}
}
impl<T: std::clone::Clone> UnshiftMemoryHog<T> for Vec<T> {
fn unshift_memory_hog(&mut self, s: Vec<T>) -> ()
where
T: std::clone::Clone,
{
let mut tmp: Vec<_> = s.to_owned();
//let mut tmp: Vec<_> = s.clone(); // this also works for some data types
/*
let local_s: Vec<_> = self.clone(); // explicit clone()
tmp.extend(local_s); // to vec is possible
*/
tmp.extend(self.clone());
*self = tmp;
//*self = (*tmp).to_vec(); // Just because it compiles, doesn't make it right.
}
}
// this works for: v = unshift(v, &vec![8]);
// (If you don't want to impl Unshift for Vec<T>)
#[allow(dead_code)]
fn unshift_fn<T>(v: Vec<T>, s: &[T]) -> Vec<T>
where
T: Clone,
{
// create a mutable vec and fill it
// with a clone of the array that we want
// at the start of the vec.
let mut tmp: Vec<_> = s.to_owned();
// then we add the existing vector to the end
// of the temporary vector.
tmp.extend(v);
// return the tmp vec that is identitcal
// to unshift-ing the original vec.
tmp
}
/*
N.B. It is sometimes (often?) more memory efficient to reverse
the vector and use push/pop, rather than splice/drain;
Especially if you create your vectors in "stack order" to begin with.
*/
fn main() {
let mut v: Vec<usize> = vec![1, 2, 3];
println!("Before push:\t {:?}", v);
v.push(0);
println!("After push:\t {:?}", v);
v.pop();
println!("popped:\t\t {:?}", v);
v.drain(0..1);
println!("drain(0..1)\t {:?}", v);
/*
// We could use a function
let c = v.clone();
v = unshift_fn(c, &vec![0]);
*/
v.splice(0..0, vec![0]);
println!("splice(0..0, vec![0]) {:?}", v);
v.shift_n(1);
println!("shift\t\t {:?}", v);
v.unshift_memory_hog(vec![8, 16, 31, 1]);
println!("MEMORY guzzler unshift {:?}", v);
//v.drain(0..3);
v.drain(0..=2);
println!("back to the start: {:?}", v);
v.unshift_vec(vec![0]);
println!("zerothed with unshift: {:?}", v);
let mut w = vec![4, 5, 6];
/*
let prepend_this = &[1, 2, 3];
w.unshift_vec(prepend_this.to_vec());
*/
w.unshift(&[1, 2, 3]);
assert_eq!(&w, &[1, 2, 3, 4, 5, 6]);
println!("{:?} == {:?}", &w, &[1, 2, 3, 4, 5, 6]);
}

Get the number of elements stored inside an n-dimensional vector

I have a 2-dimensional vector:
let vec2d = vec![
vec![1, 1, 1],
vec![1, 1, 1],
];
I can yield the total of elements stored this way:
let mut n_vec_element: i32 = 0;
for i in vec2d.iter() {
n_vec_element += i.len() as i32;
}
println!("2D vector elements :{}", n_vec_element); // prints 6
When I increase the dimensions, the loop gets longer:
let mut n_vec_element: i32 = 0;
let vec3d = vec![
vec![
vec![1, 3, 5 as i32],
vec![2, 4, 6 as i32],
vec![3, 5, 7 as i32],
],
vec![
vec![1, 3, 5 as i32],
vec![2, 4, 6 as i32],
vec![3, 5, 7 as i32],
]
];
for i in vec3d.iter() {
// I must add another iter everytime I increment the dimension by 1.
// Else, it returns the number of stored vector instead of the vector
// elements.
for j in i.iter() {
n_vec_size += j.len() as i32;
}
};
println!("3D vector elements :{}", n_vec_element); // prints 18
There must be a more concise way to do this, but I haven't figured it out yet. Initially, I tried using vector's len() function but as I said above, it returns number of vectors stored instead of its elements.
You do not need an explicit loop to do so:
let vec2d = vec![
vec![1, 1, 1],
vec![1, 1, 1],
];
let n_vec_element: usize = vec2d.iter().map(Vec::len).sum();
assert_eq!(n_vec_element, 6);
For a 3d vector, you can do the same:
let vec3d = vec![
vec![
vec![1, 3, 5 as i32],
vec![2, 4, 6 as i32],
vec![3, 5, 7 as i32],
],
vec![
vec![1, 3, 5 as i32],
vec![2, 4, 6 as i32],
vec![3, 5, 7 as i32],
]
];
let n_vec_element: usize = vec3d.iter().flatten().map(Vec::len).sum();
assert_eq!(n_vec_element, 18);
With a 4D vector, you can put 2 flatten, etc.
With the specialization feature (i.e., with the nightly compiler), you can generalize this with an unique method:
#![feature(specialization)]
trait Count {
fn count(self) -> usize;
}
impl<T> Count for T {
default fn count(self) -> usize {
1
}
}
impl<T> Count for T
where
T: IntoIterator,
T::Item: Count,
{
fn count(self) -> usize {
self.into_iter().map(|x| x.count()).sum()
}
}
fn main() {
let v = vec![1, 2, 3];
assert_eq!(v.count(), 3);
let v = vec![vec![1, 2, 3], vec![4, 5, 6]];
assert_eq!(v.count(), 6);
}

How can I conveniently convert a 2-dimensional array into a 2-dimensional vector?

I'm following the Rust-wasm tutorial and I want to be able to easily add a ship (a shape really) to the Universe in the game of life.
As a first step, I'd like to convert a 2-dimensional array of 0 or 1 representing a shape into a vector of indices representing the coordinates of the shape in the Universe.
I have a working piece of code but I'd like to make it a bit more user-friendly:
const WIDTH: u32 = 64;
const HEIGHT: u32 = 64;
/// glider: [[0, 1, 0], [0, 0, 1], [1, 1, 1]]
fn make_ship(shape: Vec<Vec<u32>>) -> Vec<u32> {
let mut ship: Vec<u32> = Vec::new();
for row_idx in 0..shape.len() {
for col_idx in 0..shape[row_idx].len() {
let cell = shape[row_idx][col_idx];
if cell == 1 {
ship.push(col_idx as u32 + row_idx as u32 * WIDTH);
}
}
}
ship
}
#[test]
fn glider() {
let glider = vec![vec![0, 1, 0], vec![0, 0, 1], vec![1, 1, 1]];
println!("{:?}", make_ship(glider));
}
The test shows my problem: the verbosity of vec!s. Ideally I'd like to be able to write it without all the vec!. The code of make_ship shouldn't care about the size of the shape arrays. Ideal example:
let glider = [[0, 1, 0],
[0, 0, 1],
[1, 1, 1],];
The question is: how to express a shape nicely with simple arrays and have the function make_ship take 2-dimensional vectors of arbitrary size?
Reducing the number of vec!s is possible with a custom macro:
#[macro_export]
macro_rules! vec2d {
($($i:expr),+) => { // handle numbers
{
let mut ret = Vec::new();
$(ret.push($i);)*
ret
}
};
([$($arr:tt),+]) => { // handle sets
{
let mut ret = Vec::new();
$(ret.push(vec!($arr));)*
ret
}
};
}
fn main() {
let glider = vec2d![[0, 1, 0],
[0, 0, 1],
[1, 1, 1]];
let glider2 = vec2d![[0, 1, 0, 1],
[0, 0, 1, 0],
[1, 1, 1, 0],
[0, 1, 1, 0]];
println!("{:?}", glider); // [[0, 1, 0], [0, 0, 1], [1, 1, 1]]
println!("{:?}", glider2); // [[0, 1, 0, 1], [0, 0, 1, 0], [1, 1, 1, 0], [0, 1, 1, 0]]
}
Your initial function could also use a bit of an improvement with the help of Rust's iterators:
fn make_ship(shape: Vec<Vec<u32>>) -> Vec<u32> {
shape
.iter()
.enumerate()
.flat_map(|(row, v)| {
v.iter().enumerate().filter_map(move |(col, x)| {
if *x == 1 {
Some(col as u32 + row as u32 * WIDTH)
} else {
None
}
})
})
.collect()
}
Vec<Vec<_>> is actually not a 2-dimensional vector but a "vector of vectors". This has major implications (assuming the outer vector is interpreted as rows, and the inner as columns):
Rows can have different lengths. That is often not what you would want.
Rows are individual objects, potentially scattered all over the heap memory.
In order to access an element you have to follow two indirections.
I would implement a 2-dimensional vector rather as a 1-dimensional vector with additional information regarding its dimensions. Something like:
struct Vec2D<T> {
n_rows: usize, // number of rows
n_cols: usize, // number of columns (redundant, since we know the length of data)
data: Vec<T>, // data stored in a contiguous 1D array
}
This struct can be initialized with
let glider = Vec2D {
n_rows: 3,
n_cols: 3,
data: vec![0, 1, 0,
0, 0, 1,
1, 1, 1],
};
Or more conveniently with functions or macros that take arrays-of-arrays. (See #ljedrz's answer for inspiration).
To access an element in the struct you'd have to use a little bit of math to convert a 2D index into a 1D index:
impl<T> Vec2D<T> {
fn get(&self, row: usize, col: usize) -> &T {
assert!(row < self.n_rows);
assert!(col < self.n_cols);
&self.data[row * self.n_cols + col]
}
}
While implementing your own 2-dimensional array type is a fun exercise, for productive use it may be more efficient to use an existing solution such as the ndarray crate.
Another solution is to transparently handle Vec<T> and [T] using AsRef:
fn make_ship<T>(shape: &[T]) -> Vec<u32>
where
T: AsRef<[u32]>,
{
let mut ship: Vec<u32> = Vec::new();
for row_idx in 0..shape.len() {
let row = shape[row_idx].as_ref();
for col_idx in 0..row.len() {
let cell = row[col_idx];
if cell == 1 {
ship.push(col_idx as u32 + row_idx as u32 * WIDTH);
}
}
}
ship
}
This handles the following:
let glider = vec![vec![0, 1, 0], vec![0, 0, 1], vec![1, 1, 1]];
let glider = [[0, 1, 0], [0, 0, 1], [1, 1, 1]];
let glider = [vec![0, 1, 0], vec![0, 0, 1], vec![1, 1, 1]];
let glider = vec![[0, 1, 0], [0, 0, 1], [1, 1, 1]];
An even better solution is to not care about slices/vectors at all, and use iterators:
fn make_ship<'a, T, U>(shape: &'a T) -> Vec<u32>
where
&'a T: std::iter::IntoIterator<Item = U>,
U: std::iter::IntoIterator<Item = &'a u32>,
{
let mut ship: Vec<u32> = Vec::new();
for (row_idx, row) in shape.into_iter().enumerate() {
for (col_idx, &cell) in row.into_iter().enumerate() {
if cell == 1 {
ship.push(col_idx as u32 + row_idx as u32 * WIDTH);
}
}
}
ship
}
Which also handle the cases above, but could also handle a type such as #kazemakase's Vec2D if it provided such iterators.

How to increment every number in a vector without the error "cannot borrow as mutable more than once at a time"?

This code is supposed to increment each value in a vector by 1:
fn main() {
let mut v = vec![2, 3, 1, 4, 2, 5];
let i = v.iter_mut();
for j in i {
*j += 1;
println!("{}", j);
}
println!("{:?}", &mut v);
}
It doesn't work because of the borrowing rules of Rust:
error[E0499]: cannot borrow `v` as mutable more than once at a time
--> src/main.rs:8:27
|
3 | let i = v.iter_mut();
| - first mutable borrow occurs here
...
8 | println!("{:?}", &mut v);
| ^ second mutable borrow occurs here
9 | }
| - first borrow ends here
How can I accomplish this task?
Don't store the mutable iterator; use it directly in the loop instead:
fn main() {
let mut v = vec![2, 3, 1, 4, 2, 5];
for j in v.iter_mut() { // or for j in &mut v
*j += 1;
println!("{}", j);
}
println!("{:?}", &v); // note that I dropped mut here; it's not needed
}
Your code will work as-is in a future version of Rust thanks to non-lexical lifetimes:
#![feature(nll)]
fn main() {
let mut v = vec![2, 3, 1, 4, 2, 5];
let i = v.iter_mut();
for j in i {
*j += 1;
println!("{}", j);
}
println!("{:?}", &mut v);
}
playground
You call also just use map and collect like,
>> let mut v = vec![5,1,4,2,3];
>> v.iter_mut().map(|x| *x += 1).collect::<Vec<_>>();
>> v
[6, 2, 5, 3, 4]
In my opinion the simplest and most readable solution:
#![feature(nll)]
fn main() {
let mut v = vec![2, 3, 1, 4, 2, 5];
for i in 0..v.len() {
v[i] += 1;
println!("{}", j);
}
println!("{:?}", v);
}

How do I get a slice of a Vec<T> in Rust?

I can not find within the documentation of Vec<T> how to retrieve a slice from a specified range.
Is there something like this in the standard library:
let a = vec![1, 2, 3, 4];
let suba = a.subvector(0, 2); // Contains [1, 2];
The documentation for Vec covers this in the section titled "slicing".
You can create a slice of a Vec or array by indexing it with a Range (or RangeInclusive, RangeFrom, RangeTo, RangeToInclusive, or RangeFull), for example:
fn main() {
let a = vec![1, 2, 3, 4, 5];
// With a start and an end
println!("{:?}", &a[1..4]);
// With a start and an end, inclusive
println!("{:?}", &a[1..=3]);
// With just a start
println!("{:?}", &a[2..]);
// With just an end
println!("{:?}", &a[..3]);
// With just an end, inclusive
println!("{:?}", &a[..=2]);
// All elements
println!("{:?}", &a[..]);
}
If you wish to convert the entire Vec to a slice, you can use deref coercion:
fn main() {
let a = vec![1, 2, 3, 4, 5];
let b: &[i32] = &a;
println!("{:?}", b);
}
This coercion is automatically applied when calling a function:
fn print_it(b: &[i32]) {
println!("{:?}", b);
}
fn main() {
let a = vec![1, 2, 3, 4, 5];
print_it(&a);
}
You can also call Vec::as_slice, but it's a bit less common:
fn main() {
let a = vec![1, 2, 3, 4, 5];
let b = a.as_slice();
println!("{:?}", b);
}
See also:
Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?

Resources