I'm trying to do the following in Rust, specifically using arrays (I don't want to use vectors here, and want elements pushed out of the array if we're done).
let mut x = [1, 2, 3, 4, 5];
// array, number to insert, place to be inserted at
insert_in_place(&x, 7, 1);
// x is now [1, 7, 2, 3, 4];
How do you implement insert_in_place?
I think there's a way to do this using slices, but I'm still learning and wondering if there's a really elegant way to do this kind of thing.
fn insert_in_place<T>(array: &mut [T], value: T, index: usize) {
*array.last_mut().unwrap() = value;
array[index..].rotate_right(1);
}
Try it online!
Or equivalently:
fn insert_in_place<T>(array: &mut [T], value: T, index: usize) {
array[index..].rotate_right(1);
array[index] = value;
}
Try it online!
Iterate the slice, skipping elements before the index of the one you need to insert. Then swap each element with its previous element (or, for the first one, use the item to add).
fn insert_in_place<T>(x: &mut [T], new: T, index: usize) {
let mut next = new;
for e in x.iter_mut().skip(index) {
std::mem::swap(e, &mut next);
}
}
fn main() {
let mut x = [1, 2, 3, 4, 5];
// array, number to insert, place to be inserted at
insert_in_place(&mut x, 7, 1);
// x is now [1, 7, 2, 3, 4];
println!("{:?}", x);
}
Related
I have to Vecs: vec_a and vec_b. Both the same size. I want to perform element-wise subtraction between the two vectors and save the answer in a third vector vec_c. For example:
vec_a = [1, 2, 3]
vec_b = [0, 2, -3]
vec_c = vec_a - vec_b = [1, 0, 6]
The solution I've come with is this function:
pub fn elementwise_subtraction(vec_a: Vec<i32>, vec_b: Vec<i32>) -> Vec<i32> {
let mut vec_c = Vec::new();
for i in 0..vec_a.len() {
vec_c.push(vec_a[i] - vec_b[i]);
}
vec_c
}
I feel like this is a bit verbose for a pretty simple operation. Is there a better/more idiomatic way to do this?
There is no such thing built in, you have to implement it yourself or use a third-party crate.
Anyway, you can continue to improve your code using functional programming:
pub fn elementwise_subtraction(vec_a: Vec<i32>, vec_b: Vec<i32>) -> Vec<i32> {
vec_a.into_iter().zip(vec_b).map(|(a, b)| a - b).collect()
}
let vec_a = vec![1, 2, 3];
let vec_b = vec![0, 2, -3];
let vec_c = elementwise_subtraction(vec_a, vec_b);
assert_eq!(vec_c, [1, 0, 6])
If you want to make it more generic (e.g. accepting both slices or Vec, any subtractable type):
use std::ops::Sub;
pub fn elementwise_subtraction<N, IA, IB, F>(a: IA, b: IB) -> F
where
N: Sub,
IA: IntoIterator<Item = N>,
IB: IntoIterator<Item = N>,
F: FromIterator<N> + FromIterator<<N as Sub>::Output>,
{
a.into_iter().zip(b).map(|(a, b)| a - b).collect()
}
let vec_a = [1, 2, 3];
let vec_b = [0, 2, -3];
let vec_c: Vec<_> = elementwise_subtraction(vec_a, vec_b);
assert_eq!(vec_c, [1, 0, 6])
Try it on playground
You'll need to use zip and map:
fn main() {
let vec_a = [1, 2, 3];
let vec_b = [0, 2, -3];
let vec_c: Vec<i32> = vec_a
.iter()
.zip(vec_b)
.map(|(elem_a, elem_b)| elem_a - elem_b)
.collect();
for elem_c in vec_c {
println!("{}", elem_c);
}
}
Your method is likely the most efficient way since it uses straight indexing, but an iterator method could look like this:
assert_eq!(
vec_a
.iter()
.zip(vec_b)
.map(|(a, b)| a - b)
.collect::<Vec<_>>(),
vec![1, 0, 6]
);
"Better" is always subjective, so if performance is your priority you should benchmark different methods; I've been surprised by results before.
code first:
use std::collections::HashMap;
macro_rules! arr{
([$($t:expr=>[$($c:expr),*]),*]) => {
vec![
$({
let mut m = HashMap::new();
m.insert($t, vec![$($c),*]);
m
}),*
]
};
}
fn main() {
let a = arr!([
"A"=>[1,2,3],
"B"=>[3,4]
]);
println!("{:?}", a);
//print: [{"A": [1, 2, 3]}, {"B": [3, 4]}]
}
I have above macro to generate a vec, contains several HashMap, in which these HashMap value is a vec as well,
{"A": [1, 2, 3]} => vec value length: 3,
{"B": [3, 4]} => vec value length: 2,
I wanna all the HashMap have the same length,
how to write in the macro to control this?
You can change the macro so that it creates a block (second set of {} encapsulating the macro definition) that you can set helper variables in and do a second pass over your vector, resizing anything that is smaller than the largest array.
In this case I've resized the arrays with the default value of the type to keep it simple. You may wish to wrap the data in Some().
This:
use std::cmp;
use std::collections::HashMap;
use std::default::Default;
macro_rules! arr{
([$($t:expr=>[$($c:expr),*]),*]) => {{
let mut max = 0;
let mut result = vec![
$({
let mut m = HashMap::new();
m.insert($t, vec![$($c),*]);
// Simply unwrap here as we know we inserted at this key above
max = cmp::max(max, m.get($t).unwrap().len());
m
}),*
];
for m in result.iter_mut() {
for v in m.values_mut() {
if v.len() < max {
v.resize_with(max, Default::default);
}
}
}
result
}};
}
fn main() {
let a = arr!([
"A"=>[1,2,3],
"B"=>[3,4]
]);
println!("{:?}", a);
//print: [{"A": [1, 2, 3]}, {"B": [3, 4]}]
}
Yields:
[{"A": [1, 2, 3]}, {"B": [3, 4, 0]}]
Given a vector of vectors of some value T, ie. Vec<Vec<T>>.
What's the idiomatic way to check if the inner vectors have the same length? (without external dependencies)
That is, true if all the inner vectors have the same length, and false otherwise.
You can use the all method to check if all elements of an iterator match a predicate. Then just compare against the first element in the list.
fn main() {
let vec_of_vecs = vec![
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3, 4], // remove this to prove that it works for both cases
];
let all_same_length = vec_of_vecs
.iter()
.all(|ref v| v.len() == vec_of_vecs[0].len());
if all_same_length {
println!("They're all the same");
} else {
println!("They are not the same");
}
}
An other solution more generic and idiomatic in my opinion:
fn all_eq_len<'a, T, E: 'a>(collection: T) -> bool
where
T: IntoIterator<Item = &'a Vec<E>>,
{
let mut iter = collection.into_iter();
if let Some(first) = iter.next() {
let len = first.len();
iter.all(|v| v.len() == len)
} else {
true
}
}
And of course using itertools:
use itertools::Itertools;
vec_of_vecs.iter().map(|v| v.len()).all_equal()
How do I cycle through an iterator a finite number of times?
I would expect the output of something like this to be 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3 and then stop:
vec![1, 2, 3].iter().cycle(4)
// ^ but .cycle() doesn't take an argument...
I don't know the length of the iterator to begin with.
One simple way is to repeat the iterator itself, take the first 4 and flatten:
fn main() {
let v = vec![1, 2, 3];
let res = std::iter::repeat(v.iter())
.take(4)
.flatten()
.collect::<Vec<_>>();
dbg!(res);
}
Some micro-benchmark result using code in this gist comparing 3 different approaches:
repeat-take-flatten in this answer
hand-rolled loop
a cycle_n implementation mimicking Iterator::cycle.
Kudos to rustc, cycle_n consistently outperforms the other two when the input is reasonably large whereas repeat-take-flatten performs the best for small input.
There is no such an iterator in the std lib.
If you know the iterator size, you can take your number times the size of the iterator:
fn cycle_n_times<T: Clone>(slice: &[T], count: usize) -> impl Iterator<Item = &T> {
slice.iter().cycle().take(slice.len() * count)
}
Or you can write your own that is more general:
pub struct Ncycles<I> {
orig: I,
iter: I,
count: usize,
}
impl<I: Clone> Ncycles<I> {
fn new(iter: I, count: usize) -> Ncycles<I> {
Ncycles {
orig: iter.clone(),
iter,
count,
}
}
}
impl<I> Iterator for Ncycles<I>
where
I: Clone + Iterator,
{
type Item = <I as Iterator>::Item;
#[inline]
fn next(&mut self) -> Option<<I as Iterator>::Item> {
match self.iter.next() {
None if self.count == 0 => None,
None => {
self.iter = self.orig.clone();
self.count -= 1;
self.iter.next()
}
y => y,
}
}
}
#[test]
fn it_work() {
Ncycles::new(vec![1, 2, 3].iter(), 4).eq(&[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]);
}
One could leverage slice::repeat, but I can't imagine this is very efficient:
let v = vec![1, 2, 3];
let it = v.iter();
println!("{:?}", it.map(|x| *x).collect::<Vec<i32>>().repeat(4).iter());
Given a vector of vectors of some value T, ie. Vec<Vec<T>>.
What's the idiomatic way to check if the inner vectors have the same length? (without external dependencies)
That is, true if all the inner vectors have the same length, and false otherwise.
You can use the all method to check if all elements of an iterator match a predicate. Then just compare against the first element in the list.
fn main() {
let vec_of_vecs = vec![
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3],
vec![1, 2, 3, 4], // remove this to prove that it works for both cases
];
let all_same_length = vec_of_vecs
.iter()
.all(|ref v| v.len() == vec_of_vecs[0].len());
if all_same_length {
println!("They're all the same");
} else {
println!("They are not the same");
}
}
An other solution more generic and idiomatic in my opinion:
fn all_eq_len<'a, T, E: 'a>(collection: T) -> bool
where
T: IntoIterator<Item = &'a Vec<E>>,
{
let mut iter = collection.into_iter();
if let Some(first) = iter.next() {
let len = first.len();
iter.all(|v| v.len() == len)
} else {
true
}
}
And of course using itertools:
use itertools::Itertools;
vec_of_vecs.iter().map(|v| v.len()).all_equal()