A variadic function takes a variable number of arguments of same type. Macro function !product from Itertools package are one of those and I'd like to compute it with a vector of ranges.
Example usage of !product is following where each argument is a Range
use itertools::iproduct;
// Iterate over the coordinates of a 4 x 4 x 4 grid
// from (0, 0, 0), (0, 0, 1), .., (0, 1, 0), (0, 1, 1), .. etc until (3, 3, 3)
for (i, j, k) in iproduct!(0..4, 0..4, 0..4) {
// ..
}
How can I call iproduct with an iterator or a vector where each element will become each argument into iproduct? For instance
use std::ops::Range;
let ranges : Vec<Range<i64>> = vec![
Range {start: 5, end: 10},
Range {start: 0, end: 10},
Range {start: -2, end: 3}
];
// How to call here properly??
for (i, j, k) in iproduct!(ranges) {
// ..
}
Side note:
For instance in python, one would call the function using the star sign before the variable: product(*ranges).
I think you're looking for Itertools::multi_cartesian_product
use itertools::Itertools;
use std::ops::Range;
fn main() {
let ranges: Vec<Range<i64>> = vec![
5..10,
0..10,
-2..3,
];
// How to call here properly??
for v in ranges.into_iter().multi_cartesian_product() {
let i = v[0];
let j = v[1];
let k = v[2];
// ..
}
}
Related
I have a BTreeSet object and I want to convert it into a BTreeMap with default indices (i.e., starting from 0 and incrementing). More precisely, given this:
let set = BTreeSet::from([0, 2, 4, 6, 8]);
I want to end up with BTreeMap<usize, usize> that holds [(0, 0), (1, 2), (2, 4), (3, 6), (4, 8)]. I can do it with a loop for example as
let mut tree = BTreeMap::new();
for (i, v) in set.clone().into_iter().enumerate() {
tree.insert(i, v);
}
But is there any shortcut (i.e., one line code) that does the same?
But is there any shortcut (i.e., one line code) that does the same?
let map = set.iter().copied().enumerate().collect::<BTreeMap<_, _>>();
println!("{:?}", map);
{0: 0, 1: 2, 2: 4, 3: 6, 4: 8}
tho note that this is a BTreeMap<usize, i32>, because i32 is the default resolution for {integer} literals if they're otherwise unconstrained, which is the case here.
I have a vector of some elements that I would like to iterate from some index and cycle around from the front again while only visiting each element a single time.
Ex. starting here at index 2,
[0, 1, 2, 3, 4, 5, 6]
^
I would like to have an iterator over the elements [2, 3, 4, 5, 6, 0, 1] (and avoid writing a loop everywhere I need to run through the vector this way).
The standard iteration with cycle() + skip() seemed to be a good start, but it of cause never ends.
Is there any idiomatic way with rusts standard iterators?
You can iterate over the two subslices, and use chain to concatenate them together into a single iterator:
let v = vec![0, 1, 2, 3, 4, 5, 6];
let start_index = 2;
for e in v[start_index..].iter().chain(v[..start_index].iter()) {
println!("{}", e);
}
The obvious fix for your cycle/skip combo is to add a take() to limit it:
fn cycle<T>(slice: &[T], start_pos: usize) -> impl Iterator<Item = &T> {
slice.iter().cycle().skip(start_pos).take(slice.len())
}
Another option is to just chain the two ranges, which even ends up a bit shorter:
fn cycle<T>(slice: &[T], start_pos: usize) -> impl Iterator<Item = &T> {
slice[start_pos..].iter().chain(&slice[..start_pos])
}
Both versions pass test such as:
let v = vec![0, 1, 2, 3, 4, 5, 6];
assert_eq!(cycle(&v, 2).copied().collect::<Vec<_>>(), vec![2, 3, 4, 5, 6, 0, 1]);
Say I have an array of primitive integers of length N, and I want to create a new array of the same length by applying a function to each element in the original array. For example, with the swap_bytes method:
let arr: [u64; 4] = [1, 2, 3, 4];
let output: [u64; 4] = [1u64.swap_bytes(), 2u64.swap_bytes(), 3u64.swap_bytes(), 4u64.swap_bytes()];
// Just an example to show the desired output,
// obviously a generic function wouldn't use this code
My question is: would it be faster to make the output array a [MaybeUninit<u64>; 4] to begin with, or would it be just as fast to initialise the output array with zeros ([0u64; 4]), as the element type of the array is a primitive integer?
So basically I'm asking which of these two pieces of code would be faster, and why:
let arr: [u64; 4] = [1, 2, 3, 4];
let mut out = MaybeUninit::uninit_array::<4>();
for i in 0..4 {
out[i] = MaybeUninit::new(arr[i].swap_bytes());
}
MaybeUninit::array_assume_init(out)
or
let arr: [u64; 4] = [1, 2, 3, 4];
let mut out = [0u64; 4];
for i in 0..4 {
out[i] = arr[i].swap_bytes();
}
out
I was looking at the documentation and found an example code that looked unfamiliar.
std::cmp::Reverse - Rust
use std::cmp::Reverse;
let mut v = vec![1, 2, 3, 4, 5, 6];
v.sort_by_key(|&num| (num > 3, Reverse(num)));
assert_eq!(v, vec![3, 2, 1, 6, 5, 4]);
How does (num > 3, Reverse(num)) define ordering between themselves?
I had a look into documentation for tuple, and it said
The sequential nature of the tuple applies to its implementations of various traits. For example, in PartialOrd and Ord, the elements are compared sequentially until the first non-equal set is found.
That makes sense for equality checks, but it seems to me that it does not give explanation for how > and < acts on tuples.
I did some experiments, but understood nothing.
println!("{}", (5, 5) > (3, 4)); // true
println!("{}", (2, 2) > (3, 4)); // false
println!("{}", (2, 5) > (3, 4)); // false
println!("{}", (3, 5) > (3, 4)); // true
println!("{}", (5, 2) > (3, 4)); // true
As what you quoted notes, tuples are compared lexicographically.
That is, the first elements of each tuple are compared, then if they're equal the second elements are, then the third, etc.. until a non-equal pair is found and provides the ordering of the tuples. If all pairs are equal then the tuples are, obviously, equal.
println!("{}", (5, 5) > (3, 4)); // true
5 > 3, therefore (5, _) > (3, _)
println!("{}", (2, 2) > (3, 4)); // false
2 < 3, therefore (2, _) < (3, _)
println!("{}", (2, 5) > (3, 4)); // false
see above
println!("{}", (3, 5) > (3, 4)); // true
3 == 3, 5 > 4, therefore (3, 5) > (3, 4)
println!("{}", (5, 2) > (3, 4)); // true
see first case
How does (num > 3, Reverse(num)) define ordering between themselves?
booleans sort false < true, therefore it first orders the elements in two broad categories (numbers below 3 then numbers above 3) then within each category items are ordered based on their reverse natural order (that is, largest-first). Though it obviously does that in a single pass.
You can read the source code of tuple:
impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+)
where last_type!($($T,)+): ?Sized {
#[inline]
fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
lexical_partial_cmp!($(self.$idx, other.$idx),+)
}
// ...
#[inline]
fn gt(&self, other: &($($T,)+)) -> bool {
lexical_ord!(gt, $(self.$idx, other.$idx),+)
}
}
And the lexical_ord macro:
// Constructs an expression that performs a lexical ordering using method $rel.
// The values are interleaved, so the macro invocation for
// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2,
// a3, b3)` (and similarly for `lexical_cmp`)
macro_rules! lexical_ord {
($rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
if $a != $b { lexical_ord!($rel, $a, $b) }
else { lexical_ord!($rel, $($rest_a, $rest_b),+) }
};
($rel: ident, $a:expr, $b:expr) => { ($a) . $rel (& $b) };
}
So (a, b) > (c, d) will call (a, b).gt(&(c, d)), which will use the lexical_ord macro like this (see comment in the code):
lexical_ord(gt, a, c, b, d)
(Actually, it should be something like lexical_ord(gt, (a, b).0, (c, d).0, (a, b).1, (c, d).1), if I'm reading the macro correctly, but I've simplified it here.)
Which will be translated (at compile-time) to this:
if a != c {
(a).gt(&c)
} else {
(b).gt(&d)
}
So the actual code that will be called for (a, b) > (c, d) will be:
fn gt(&self, other: &($T, $T)) -> bool {
if self.0 != other.0 {
(self.0).gt(&other.0) // self.0 > other.0
} else {
(self.1).gt(&other.1) // self.1 > other.1
}
}
So it's comparing the values in each tuple one-by-one in pairs.
That makes sense for equality checks, but it seems to me that it does not give explanation for how > and < acts on tuples.
It does, consider the examples you gave:
println!("{}", (5, 5) > (3, 4)); // 5 > 3 is true
println!("{}", (2, 2) > (3, 4)); // 2 > 3 is false
println!("{}", (2, 5) > (3, 4)); // 2 > 3 is false
println!("{}", (3, 5) > (3, 4)); // 3 == 3, then: 5 > 4 is true
println!("{}", (5, 2) > (3, 4)); // 5 > 3 is true
It returns the result of </> of the first non-equal element of the tuple.
I have a slice of bytes start = [30u8; 5] and middle = [40u8; 3] and a vector of byte slices:
let first = [1u8; 10];
let second = [2u8; 10];
let third = [3u8; 10];
let elements: Vec<[u8; 10]> = vec![first, second, third];
I want to concatenate everything together, in such a way that I will obtain a single byte slice which looks as
[30, 30, 30, 30, 30, 40, 40, 40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
However, although I can concatenate start and middle when I try to append the vector elements it fails. I know that I am wrongly trying to iterate through the elements of the vector to concatenate, but I can't figure out how to do it correctly?
fn main() {
let start = [30u8; 5];
let middle = [40u8; 4];
let first = [1u8; 10];
let second = [2u8; 10];
let third = [3u8; 10];
let elements: Vec<[u8; 10]> = vec![first, second, third];
println!("{:?}", elements.iter());
for key in elements.iter() {
println!("{:?}", key.iter());
}
let alltogether: Vec<u8> = start
.iter()
.cloned()
.chain(middle.iter().cloned())
.chain(elements.iter().iter().cloned())
.collect();
println!("{:?}", alltogether);
}
This example can be copy-pasted into the Rust playground.
You possibly want this:
let alltogether: Vec<u8> = start
.iter()
.cloned()
.chain(middle.iter().cloned())
.chain(elements.iter().flatten().cloned())
.collect();
Note that there is also copied (instead of cloned) that can be used for Copyable types.
If the stuff in elements does not implement IntoIterator itself, you can use flat_map to specify how to convert one element to an iterator.