So I have a Vec<Vec<T>> where the first vector groups by hours of day and the inner vector by days of week. I would like to transpose somehow the vectors to have it first by days then by hours. Is there a simple way to do it in Rust?
EDIT: I mean, I know how to do it with 2 for loops but is there a smarter/shorter way to do it functionally
You can use some iterators:
fn transpose<T>(v: Vec<Vec<T>>) -> Vec<Vec<T>>
where
T: Clone,
{
assert!(!v.is_empty());
(0..v[0].len())
.map(|i| v.iter().map(|inner| inner[i].clone()).collect::<Vec<T>>())
.collect()
}
As user4815162342 comments, here is a version without Clone:
fn transpose2<T>(v: Vec<Vec<T>>) -> Vec<Vec<T>> {
assert!(!v.is_empty());
let len = v[0].len();
let mut iters: Vec<_> = v.into_iter().map(|n| n.into_iter()).collect();
(0..len)
.map(|_| {
iters
.iter_mut()
.map(|n| n.next().unwrap())
.collect::<Vec<T>>()
})
.collect()
}
Playground
The question says "I know how to do it with 2 for loops but is there a smarter/shorter way to do it functionally", however that it is probably the best answer for the title. Here's a two-for-loop solution that avoids T: Clone and avoids allocating a scratch Vec for iterators:
fn transpose<T>(original: Vec<Vec<T>>) -> Vec<Vec<T>> {
assert!(!original.is_empty());
let mut transposed = (0..original[0].len()).map(|_| vec![]).collect::<Vec<_>>();
for original_row in original {
for (item, transposed_row) in original_row.into_iter().zip(&mut transposed) {
transposed_row.push(item);
}
}
transposed
}
Someone could probably make it more "functional" than I, but this is already a bit difficult to read, try as I might.
Related
When manipulating a Vector of Futures, I end up with a nested Vector of Vectors, which I then need to flatten in two iterations.
Dummy code for illustrative purposes:
use std::error::Error;
use futures::future::join_all;
#[tokio::main]
async fn main() {
async fn duplicate(number: i32) -> Result<Vec<i32>, Box<dyn Error>> {
Ok(vec!(number * 2))
}
let my_numbers = vec!(1, 2, 3, 4, 5);
let future_duplicated_evens = my_numbers.into_iter().filter_map(|number| {
if number % 2 == 0 {
Some(duplicate(number))
} else {
None
}
}).collect::<Vec<_>>();
let flattened = join_all(future_duplicated_evens).await.into_iter().collect::<Result<Vec<_>, Box<dyn Error>>>().unwrap().into_iter().flatten().collect::<Vec<i32>>();
println!("Flattened: {:?}", flattened);
}
Link to the playground.
In the sample code above, for flattened I first need to collect the Vector of Results from the joined Futures into a Result of a Vec, and after that I need to iterate again just to flatten the Vectors.
My question is, is there a way to collect and flatten in a single iteration?
Since in your example you don't care about handling the errors cleanly, you can simply apply Result::unwrap to each element using map (playground):
let flattened = join_all(future_duplicated_evens)
.await
.into_iter()
.map(Result::unwrap)
.flatten()
.collect::<Vec<i32>>();
If in your real code you do care about handling errors, you can use try_fold instead which will accumulate all of values in a single vector but abort if it comes across an error (playground):
let flattened = join_all(future_duplicated_evens)
.await
.into_iter()
.try_fold(Vec::new(), |mut acc, next| {
acc.extend_from_slice(&next?);
Ok::<Vec<i32>, Box<dyn Error>>(acc)
})
.unwrap();
I am looking for an efficient way to iterate over a permutation of the rows in a two-dimensional array in ndarray. I do not need to mutate or keep the permuted array around, so I want to avoid a copy.
That is, I want to do the following, except select allocates an unnecessary array:
use ndarray::{Axis, Array}; // 0.13.1
use rand::seq::SliceRandom; // 0.7.3
use std::iter::FromIterator;
fn main() {
let array = Array::from_iter(0..15).into_shape((5, 3)).unwrap();
println!("Before shuffling rows:\n{}", array);
let mut permutation: Vec<usize> = (0..array.nrows()).collect();
permutation.shuffle(&mut rand::thread_rng());
let permuted = array.select(Axis(0), &permutation);
for (i, row) in permuted.axis_iter(Axis(0)).enumerate() {
println!("Row number {} is {}!", i, row);
}
}
Playground.
I am aware that the ndarray Github page includes an example of something similar, but it involves a block of unsafe code that I do not understand and therefore prefer not to adapt to my own use case.
One obvious answer that I missed, using index_axis:
use ndarray::{Axis, Array}; // 0.13.1
use rand::seq::SliceRandom; // 0.7.3
use std::iter::FromIterator;
fn main() {
let array = Array::from_iter(0..15).into_shape((5, 3)).unwrap();
println!("Before shuffling rows:\n{}", array);
let mut permutation: Vec<usize> = (0..array.nrows()).collect();
permutation.shuffle(&mut rand::thread_rng());
for i in permutation.iter() {
let row = array.index_axis(Axis(0), *i);
println!("Row number {} is {}!", i, row);
}
}
I'm sure there are better ways of doing this, however, and I'm still interested to see them.
I found this way, but it seems too verbose for such a common action:
fn double_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec1 = vec.clone();
let vec2 = vec.clone();
vec1.extend(vec2);
vec1
}
I know that in JavaScript it could be just arr2 = [...arr1, ...arr1].
"Doubling a vector" isn't something that's really done very often so there's no shortcut for it. In addition, it matters what is inside the Vec because that changes what operations can be performed on it. In this specific example, the following code works:
let x = vec![1, 2, 3];
let y: Vec<_> = x.iter().cycle().take(x.len() * 2).collect();
println!("{:?}", y); //[1, 2, 3, 1, 2, 3]
The cycle() method requires that the items in the Iterator implement the Clone trait so that the items can be duplicated. So if the items in your Vec implement Clone, then this will work. Since immutable references (&) implement Clone, a Vec<&Something> will work but mutable references (&mut) do not implement Clone and thus a Vec<&mut Something> will not work.
Note that even if a type does not implement Clone, you can still clone references to that type:
struct Test;
fn test_if_clone<T: Clone>(_x: T) {}
fn main() {
let x = Test;
test_if_clone(x); //error[E0277]: the trait bound `Test: std::clone::Clone` is not satisfied
let y = &x;
test_if_clone(y); //ok
}
You can use the concat method for this, it's simple:
fn double_vec(v: Vec<i32>) -> Vec<i32> {
[&v[..], &v[..]].concat()
}
Unfortunately we have to make the vectors slices explicitly (here &v[..]); but otherwise this method is good because it allocates the result to the needed size directly and then does the copies.
Building on Wesley's answer, you can also use chain to glue two iterables together, one after the other. In the below example I use the same Vec's iter() method twice:
let x = vec![1, 2, 3];
let y: Vec<_> = x.iter().chain(x.iter()).collect();
println!("{:?}", y); //[1, 2, 3, 1, 2, 3]
The iterator methods are a likely to be a lot less efficient than a straight memcpy that vector extension is.
You own code does a clone too many; you can just reuse the by-value input:
fn double_vec(mut vec: Vec<i32>) -> Vec<i32> {
let clone = vec.clone();
vec.extend(clone);
vec
}
However, the nature of a Vec means this is likely to require a copy even if you managed to remove that clone, so you're not generally gaining much over just using concat.
Using concat on slices is fairly efficient, as it will preallocate the Vec in advance and then perform an efficient extend_from_slice. However, this does mean it's no longer particularly sensible to take a Vec as input; writing the following is strictly more flexible.
fn double_slice(slice: &[i32]) -> Vec<i32> {
[slice, slice].concat()
}
Since Rust 1.53, Vec::extend_from_within makes it possible to more efficiently double a vector:
fn double_vec(vec: &mut Vec<i32>) {
vec.extend_from_within(..);
}
To create a new vector with the contents of other vectors, I'm currently doing this:
fn func(a: &Vec<i32>, b: &Vec<i32>, c: &Vec<i32>) {
let abc = Vec<i32> = {
let mut tmp = Vec::with_capacity(a.len(), b.len(), c.len());
tmp.extend(a);
tmp.extend(b);
tmp.extend(c);
tmp
};
// ...
}
Is there a more straightforward / elegant way to do this?
There is a concat method that can be used for this, however the values need to be slices, or borrowable to slices, not &Vec<_> as given in the question.
An example, similar to the question:
fn func(a: &Vec<i32>, b: &Vec<i32>, c: &Vec<i32>) {
let abc = Vec<i32> = [a.as_slice(), b.as_slice(), c.as_slice()].concat();
// ...
}
However, as #mindTree notes, using &[i32] type arguments is more idiomatic and removes the need for conversion. eg:
fn func(a: &[i32], b: &[i32], c: &[i32]) {
let abc = Vec<i32> = [a, b, c].concat();
// ...
}
SliceConcatExt::concat is a more general version of your function and can join multiple slices to a Vec. It will sum the sizes each slice to pre-allocate a Vec of the right capacity, then extend repeatedly.
fn concat(&self) -> Vec<T> {
let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
let mut result = Vec::with_capacity(size);
for v in self {
result.extend_from_slice(v.borrow())
}
result
}
One possible solution might be to use the Chain iterator:
let abc: Vec<_> = a.iter().chain(b).chain(c).collect();
However, in your example you are borrowing the slices, so we'll need to either deref each borrowed element or use the Cloned iterator to copy each integer. Cloned is probably a bit easier and as efficient as we are working with small Copy data (i32):
let abc: Vec<_> = a.iter().cloned()
.chain(b.iter().cloned())
.chain(c.iter().cloned())
.collect();
Seeing as each of these iterators are ExactSizeIterators, it should be possible to allocate the exact size for the target Vec up front, however I'm unware whether or not this is actually the case in the std implementation (they might be waiting on specialization to land before adding this optimisation).
I have this code for reading in a 2D vector. Is there a way to eliminate the need for temp_vec?
let mut vec_size: usize = 3;
let mut vec = vec![vec![0; vec_size]; vec_size];
for i in 0..vec_size{
input = String::new();
io::stdin().read_line(&mut input).expect("Failed to read");
let temp_vec: Vec<i32> = input
.split_whitespace()
.map(|s| s.parse().unwrap())
.collect();
for j in 0..temp_vec.len(){
vec[i][j] = temp_vec[j];
}
}
I you remove the collect() call, you end up with an iterator, which you can enumerate() and just pass to the for loop:
use std::io;
fn main() {
let vec_size: usize = 3;
let mut vec = vec![vec![0; vec_size]; vec_size];
let mut input = String::new();
for i in 0..vec_size {
input.clear();
io::stdin().read_line(&mut input).expect("Failed to read");
let numbers = input
.split_whitespace()
.map(|s| s.parse().unwrap());
for (j, x) in numbers.enumerate() {
vec[i][j] = x;
}
}
}
This code also calls clear() to clear the input buffer instead of assigning new string, so it makes just one additional allocation (you may benefit from it if you're reading a lot of small matrices).
(sidenote about your code: it's better to use .iter().enumerate() than iterate on vectors indices, if you can)
When writing this answer I've misread the original question thinking that there was a stack-allocated matrix:
const VEC_SIZE: usize = 3;
let mut vec = [[0; VEC_SIZE]; VEC_SIZE];
If that was the case, I would recommend my solution, but since it's a Vec<Vec<i32>>, I'd recommend #Shepmaster's one, as it's more idiomatic.
Map the lines of standard input as the rows, then map the numbers in each row as columns.
use std::io;
use std::io::prelude::*;
const SIZE: usize = 3;
fn main() {
let stdin = io::stdin();
let vec: Vec<Vec<i32>> = stdin.lock()
.lines()
.take(SIZE)
.map(|line| {
let line = line.expect("Unable to read line");
line.split_whitespace()
.take(SIZE)
.map(|s| s.parse().expect("Enable to parse number"))
.collect()
})
.collect();
println!("{:?}", vec);
}
Or if you don't care to panic:
use std::io;
use std::io::prelude::*;
use std::error::Error;
const SIZE: usize = 3;
fn main() {
let stdin = io::stdin();
let vec: Result<Vec<Vec<i32>>, _> = stdin.lock()
.lines()
.take(SIZE)
.map(|line| {
line.map_err(|e| Box::new(e) as Box<Error>)
.and_then(|line| {
line.split_whitespace()
.take(SIZE)
.map(|s| s.parse().map_err(|e| Box::new(e) as Box<Error>))
.collect()
})
})
.collect();
println!("{:?}", vec);
}
Addressing concerns from a comment:
Your code makes 2n+1 allocations (that's important if somebody's looking for performance
It's unclear what N is here, but there should be a maximum of 3 vectors allocated and 3 items in each vector. The take adapter will override the size_hint to put a maximum of 3 and then collect will use that hint when constructing each Vec.
Using nested Vecs for matrices is an antipattern.
Absolutely, but that was what the original code did.
You "break" stdin – you can't reliably use it after calling lock().lines()
I'm not sure what you mean here. I am able to add stdin.read(&mut[0,0,0]).expect("Unable to read more") after the chunk of code that defines let vec, showing that it can be used.
If there was a problem with not being able to use stdin, you could fix it by scoping the lock to a block that ends earlier.