let mut foo: [u8; 6] = &[0, 0, 0, 0, 0, 0]
let mut bar: &[u8] = &[1, 2, 3]
I want the desired result:
&[1, 2, 3, 0, 0, 0]
The obvious way:
let foo: [u8; 6] = [bar, vec![0; 6 - bar.len()].as_slice()].concat().try_into()...
It causes a lot of overhead.
It's not practical
Perhaps there are some other ways?
Use copy_from_slice:
fn main() {
let mut foo: [u8; 6] = [0, 0, 0, 0, 0, 0];
let mut bar: &[u8] = &[1, 2, 3];
println!("before: {:?}", foo); // [0, 0, 0, 0, 0, 0]
foo[..bar.len()].copy_from_slice(bar);
println!("after: {:?}", foo); // [1, 2, 3, 0, 0, 0]
}
Like so:
fn main() {
let mut foo: [u8; 6] = [0, 0, 0, 0, 0, 0];
let mut bar: &[u8] = &[1, 2, 3];
foo[..3].clone_from_slice(bar);
println!("{:?}", foo);
}
Related
I'm trying to pass an array of arrays to a generic function in Rust, however I'm having trouble doing so.
Here's my code:
pub const T: [[u8; 3]; 2] = [[0, 1, 0], [1, 1, 1]];
pub const L: [[u8; 3]; 2] = [[0, 0, 1], [1, 1, 1]];
pub const S: [[u8; 2]; 2] = [[1, 1], [1, 1]];
pub fn insert_shape<T: Iterator>(&mut self, shape: T)
{
for (i, item) in shape.iter().enumerate()
{
for (j, element) in item.iter().enumerate()
{
self.board.set_element(i, j, element);
}
}
}
This give me an error that says type T doesn't have a method called iter. How can I fix this?
Probably best to just take the arrays:
pub fn insert_shape<const W: usize, const H: usize, T>(&mut self, shape: [[T;W];H]) {
for (i, item) in shape.iter().enumerate() {
for (j, element) in item.iter().enumerate() {
self.board.set_element(i, j, element);
}
}
}
If you really wanted you could also constrain the items of the iterator to be IntoIterator themselves.
pub fn insert_shape<I>(&mut self, shape: I)
where
I: IntoIterator,
I::Item: IntoIterator,
{
for (i, item) in shape.into_iter().enumerate() {
for (j, element) in item.into_iter().enumerate() {
self.board.set_element(i, j, element);
}
}
}
I have a function that operates on a Vec<T> which purpose is to extend the vector with new items generated using reference to existing items. I'm trying to run the generation of new data in parallel using rayon.
This is a minimal example:
use itertools::Itertools;
use rayon::prelude::*;
fn main() {
let mut foo = Foo {
data: (0..1000).into_iter().collect(),
};
foo.run();
}
struct Foo<T> {
data: Vec<T>,
}
type Pair<'a, T> = (&'a T, &'a T);
impl<'a, T: Clone + 'a> Foo<T>
where
Vec<Pair<'a, T>>: IntoParallelIterator<Item = Pair<'a, T>>,
[T; 2]: IntoParallelIterator,
Vec<T>: FromParallelIterator<<[T; 2] as IntoParallelIterator>::Item>,
{
fn run(&'a mut self) {
let combinations: Vec<Pair<'a, T>> = self
.data
.iter()
.combinations(2)
.map(|x| (x[0], x[1]))
.collect();
let mut new_combinations: Vec<T> = combinations
.into_par_iter()
.flat_map(|(a, b)| bar(a, b))
.collect();
self.data.append(&mut new_combinations);
}
}
fn bar<T: Clone>(a: &T, b: &T) -> [T; 2] {
[a.clone(), b.clone()]
}
You can find a link to Playground here.
Building the above example raises this error:
error[E0502]: cannot borrow `self.data` as mutable because it is also borrowed as immutable
--> src/main.rs:36:9
|
17 | impl<'a, T: Clone + 'a> Foo<T>
| -- lifetime `'a` defined here
...
24 | let combinations: Vec<Pair<'a, T>> = self
| ___________________________----------------___-
| | |
| | type annotation requires that `self.data` is borrowed for `'a`
25 | | .data
26 | | .iter()
| |___________________- immutable borrow occurs here
...
36 | self.data.append(&mut new_combinations);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
As far as I understand since I am collecting into a let new_combinations: Vec<T> there should be no immutable references to self.data and I should be able in theory to borrow it mutably to append the new combinations. However, it seems that self.data is borrowed for 'a which extends beyond the scope of this method. I cannot find a way to avoid specifying the lifetime fn run(&'a mut self) since I need to specify that the lifetimes of the references to the items of self.data cannot outlive self when creating the combinations.
Is there a way to allow this method to operate as expected, that is: 1) select a list of references to the items in self.data, 2) apply a function that creates new items T in parallel and finally 3) update self.data with the new items.
Note that as a workaround one could return the new_combinations from the method and append them to self.data separately.
Would be great if all of this would be possible by avoiding as many collect() as possible while operating directly with iterators only.
The elements in new_combinations are cloned and therefore don't borrow from combinations any more. Your annotations, however, state that T: 'a, meaning Rust has to treat them as still borrowed.
I personally think you are being way too excessive with the lifetimes annotations here, you could remove almost all of them. The compiler is very good in figuring them out automatically in most situations.
Further, your trait restrictions were sadly mislead by the compiler hints. They are all automatically fulfilled once you specify T: Clone + Send + Sync.
Here you go:
use itertools::Itertools;
use rayon::prelude::*;
fn main() {
let mut foo = Foo {
data: (0..10).collect(),
};
foo.run();
println!("{:?}", foo.data);
}
struct Foo<T> {
data: Vec<T>,
}
type Pair<'a, T> = (&'a T, &'a T);
impl<T: Clone + Send + Sync> Foo<T> {
fn run(&mut self) {
let combinations: Vec<Pair<T>> = self
.data
.iter()
.combinations(2)
.map(|x| (x[0], x[1]))
.collect();
let mut new_combinations: Vec<T> = combinations
.into_par_iter()
.flat_map(|(a, b)| bar(a, b))
.collect();
self.data.append(&mut new_combinations);
}
}
fn bar<T: Clone>(a: &T, b: &T) -> [T; 2] {
[a.clone(), b.clone()]
}
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 2, 3, 2, 4, 2, 5, 2, 6, 2, 7, 2, 8, 2, 9, 3, 4, 3, 5, 3, 6, 3, 7, 3, 8, 3, 9, 4, 5, 4, 6, 4, 7, 4, 8, 4, 9, 5, 6, 5, 7, 5, 8, 5, 9, 6, 7, 6, 8, 6, 9, 7, 8, 7, 9, 8, 9]
Further, there is really no need for the Pair type:
use itertools::Itertools;
use rayon::prelude::*;
fn main() {
let mut foo = Foo {
data: (0..10).collect(),
};
foo.run();
println!("{:?}", foo.data);
}
struct Foo<T> {
data: Vec<T>,
}
impl<T: Clone + Send + Sync> Foo<T> {
fn run(&mut self) {
let combinations: Vec<_> = self
.data
.iter()
.combinations(2)
.map(|x| (x[0], x[1]))
.collect();
let mut new_combinations: Vec<T> = combinations
.into_par_iter()
.flat_map(|(a, b)| bar(a, b))
.collect();
self.data.append(&mut new_combinations);
}
}
fn bar<T: Clone>(a: &T, b: &T) -> [T; 2] {
[a.clone(), b.clone()]
}
About the last part of your question, the request to remove all .collect() calls if possible:
Sadly, I don't think you will be able to remove any of the collect()s. At least not with your current code layout. You definitely need to collect() between combinations() and into_par_iter(), and you also definitely need to collect() before append, because you need to release all references to self.data before you write into it.
Suppose I have a modify_vec() function that takes a vector reference and returns a new vector. It doesn't really matter what it does so for the sake of example it will just append a given number.
fn modify_vec(v: &Vec<i64>, i: i64) -> Vec<i64> {
let mut new_v = v.clone();
new_v.push(i);
new_v
}
Now, suppose I want to run this modify_vec a few times, I could do it like that:
fn main() {
let v = vec![1, 2, 3];
println!("{:?}", run(&v)); // Outputs [1, 2, 3, 4, 5, 6]
}
fn run(v: &Vec<i64>) -> Vec<i64> {
let new_1 = modify_vec(&v, 4);
let new_2 = modify_vec(&new_1, 5);
modify_vec(&new_2, 6)
}
Or I can do it like that
fn run(v: &Vec<i64>) -> Vec<i64> {
let mut new_v = modify_vec(&v, 4);
new_v = modify_vec(&new_v, 5);
modify_vec(&new_v, 6)
}
However it would obviously be better to use a loop. The problem is that the run function starts with a reference of the vector, but it must declare a new owned variable to store the returned value of modify_vec. The only way I found to initialize that owned variable outside of the loop was doing a .clone(), like this.
fn run(v: &Vec<i64>) -> Vec<i64> {
let mut new_v = v.clone();
for i in 4..7 {
new_v = modify_vec(&new_v, i);
}
new_v
}
But this seems "wasteful", as it is my understanding that it makes a deep copy. In the previous unlooped examples, it was not necessary to clone the vector prior to passing it to the first call to modify_vec.Is there a better way?
modify_vec should take a Vec by value instead of a reference. Let the caller clone the Vec if it doesn't want to (or cannot) transfer ownership – do not impose the cost of a clone on all callers.
fn main() {
let v = vec![1, 2, 3];
println!("{:?}", run(&v)); // Outputs [1, 2, 3, 4, 5, 6]
}
fn run(v: &Vec<i64>) -> Vec<i64> {
let mut new_v = v.clone();
for i in 4..7 {
new_v = modify_vec(new_v, i);
}
new_v
}
fn modify_vec(mut v: Vec<i64>, i: i64) -> Vec<i64> {
v.push(i);
v
}
Perhaps the example is too contrived, but there is no need to clone any Vec at all:
fn main() {
let v = vec![1, 2, 3];
println!("{:?}", run(v)); // Outputs [1, 2, 3, 4, 5, 6]
// ^ this could be replaced with `v.clone()`
// if `v` needs to be used later
}
fn run(mut v: Vec<i64>) -> Vec<i64> {
for i in 4..7 {
v = modify_vec(v, i);
}
v
}
fn modify_vec(mut v: Vec<i64>, i: i64) -> Vec<i64> {
v.push(i);
v
}
I'm searching easy way to count each value in vector in Rust:
let v = vec![1, 2, 2, 1, 3, 2, 3, 5];
let counter: HashMap<_,_> = count_element_function(v);
assert_eq!(counter.get(&1), Some(2));
assert_eq!(counter.get(&2), Some(3));
assert_eq!(counter.get(&3), Some(2));
assert_eq!(counter.get(&5), Some(1));
A simple filter + count does the job if you want to count one item:
fn count<I>(it: I, item: &I::Item) -> usize
where
I: IntoIterator,
I::Item: PartialEq,
{
it.into_iter().filter(|x| x == item).count()
}
fn main() {
let v = vec![1, 2, 2, 1, 3, 2, 3, 5];
assert_eq!(count(v, &1), 2);
}
If you want to store all in the hashmap, you can do that:
use std::collections::HashMap;
fn count_element_function<I>(it: I) -> HashMap<I::Item, usize>
where
I: IntoIterator,
I::Item: Eq + core::hash::Hash,
{
let mut result = HashMap::new();
for item in it {
*result.entry(item).or_insert(0) += 1;
}
result
}
fn main() {
let v = vec![1, 2, 2, 1, 3, 2, 3, 5];
let counter: HashMap<_, _> = count_element_function(v);
assert_eq!(counter.get(&1), Some(&2));
assert_eq!(counter.get(&2), Some(&3));
assert_eq!(counter.get(&3), Some(&2));
assert_eq!(counter.get(&5), Some(&1));
}
I'm not sure that it is the most efficient, though.
Why cannot I not sort an array as expected?
fn main() {
let mut a = [1,3,2];
let s = a.sort();
println!("{:?}", s);
}
a is sorted, but the method sorts the array in place. Read the signature of sort: sort takes &mut self and returns unit (i.e. nothing), so when you print s, you print ().
Working code:
fn main() {
let mut a = [1, 3, 2];
a.sort();
assert_eq!(a, [1, 2, 3]);
println!("{:?}", a);
}
Writing a function that returns a sorted array
You can write a function that does what you want:
fn sort<A, T>(mut array: A) -> A
where
A: AsMut<[T]>,
T: Ord,
{
let slice = array.as_mut();
slice.sort();
array
}
fn main() {
let a = [1, 3, 2];
assert_eq!(sort(a), [1, 2, 3]);
}