I have a vector items of items and a vector idxs of indexes, how can I get a vector picked filled by moving all values at once from items indexed in idxs ?
For example:
let mut items: Vec<char> = ['a', 'b', 'c', 'd', 'e', 'f'];
let mut idxs: Vec<usize> = [3, 4, 1];
let picked = pick(&mut items, &idxs);
// items should be: ['a', 'c', 'f']
// picked should be: ['d', 'e', 'b']
I can make it with:
let mut picked: Vec<char> = Vec::new();
let placeholder = 'z';
for idx in idxs {
items.insert(idx, placeholder); // insert any placeholder value of type T for keeping order
let item = items.remove(idx + 1);
picked.push(item);
}
items = items.filter(|item| item != placeholder);
But I think I am overkilling it. And keeping a placeholder value for each different types is complicated, in my case I have to avoid it.
Is there a more idiomatic way to do that ?
Here are two algorithms for the problem.
The following algorithm is O(n + m). That is the best possible asymptotic run time assuming that items must stay in its original order, since that means all elements must potentially be moved to compact them after the removals.
fn pick<T>(items: &mut Vec<T>, idxs: &[usize]) -> Vec<T> {
// Move the items into a vector of Option<T> we can remove items from
// without reordering.
let mut opt_items: Vec<Option<T>> = items.drain(..).map(Some).collect();
// Take the items.
let picked: Vec<T> = idxs
.into_iter()
.map(|&i| opt_items[i].take().expect("duplicate index"))
.collect();
// Put the unpicked items back.
items.extend(opt_items.into_iter().filter_map(|opt| opt));
picked
}
fn main() {
let mut items: Vec<char> = vec!['a', 'b', 'c', 'd', 'e', 'f'];
let idxs: Vec<usize> = vec![3, 4, 1];
let picked = pick(&mut items, &idxs);
dbg!(picked, items);
}
This algorithm is instead O(m log m) (where m is the length of idxs). The price for this is that it reorders the un-picked elements of items.
fn pick<T>(items: &mut Vec<T>, idxs: &[usize]) -> Vec<T> {
// Second element is the index into `idxs`.
let mut sorted_idxs: Vec<(usize, usize)> =
idxs.iter().copied().enumerate().map(|(ii, i)| (i, ii)).collect();
sorted_idxs.sort();
// Set up random-access output storage.
let mut output: Vec<Option<T>> = Vec::new();
output.resize_with(idxs.len(), || None);
// Take the items, in reverse sorted order.
// Reverse order ensures that `swap_remove` won't move any item we want.
for (i, ii) in sorted_idxs.into_iter().rev() {
output[ii] = Some(items.swap_remove(i));
}
// Unwrap the temporary `Option`s.
output.into_iter().map(Option::unwrap).collect()
}
Both of these algorithms could be optimized by using unsafe code to work with uninitialized/moved memory instead of using vectors of Option. The second algorithm would then need a check for duplicate indices to be safe.
If idxs is unsorted and order matters, and if you can't use a placeholder, then you can move the items like this:
let mut picked: Vec<char> = Vec::new();
let mut idxs = idxs.clone(); // Not required if you are allowed to mutate the original idx.
for i in 0 .. idxs.len() {
picked.push (items.remove (idxs[i]));
for j in i+1 .. idxs.len() {
if idxs[j] > idxs[i] { idxs[j] -= 1; }
}
}
Related
I am looking for an "rusty" way to accumulate a Vec<Vec> into a Vec such that the 1st element of every inner Vec is summed together, every 2nd element of each Vec is summed together, etc..., and the results are collected into a Vec? If I just use sum(), fold(), or accumulate() I believe I will sum entire 1st Vec together into a single element, rather than the 1st element of each inner Vec contained in the 2D Vec.
pub fn main() {
let v1 = vec![1.1, 2.2, 3.3];
let vv = vec![v1; 3];
let desired_result = vec![3.3, 6.6, 9.9];
}
Sometimes it's easy to forget in Rust that the imperative approach exists and is an easy solution.
let mut sums = vec![0.0; vv[0].len()];
for v in vv {
for (i, x) in v.into_iter().enumerate() {
sums[i] += x;
}
}
While I prefer #orlp's solution, if you're hell-bent on doing this the most functionally possible, you could do it like this:
let v1 = vec![1.1, 2.2, 3.3];
let vv = vec![v1; 3];
let sums = vec![0.0; vv[0].len()];
let summed = vv.into_iter().fold(sums, |mut sums, v| {
v.into_iter().enumerate().for_each(|(i, x)| sums[i] += x);
sums
});
Also if knowing beforehand the size of the inner vectors (or taking it from the first occurence in the vv vector), you can use a range iterator:
pub fn main() {
let v1 = vec![1.1, 2.2, 3.3];
let v1_len = v1.len();
let vv = vec![v1; 3];
let res: Vec<f64> = (0..v1_len)
.map(|i| vv.iter().map(|v| v.get(i).unwrap()).sum())
.collect();
println!("{res:?}");
}
Playground
I have 2 Vecs:
let x = vec!['1', '2', '3'];
let y = vec!['a', 'b', 'c'];
Now I want to use iterator to make a new vec like this ['1a', '1b', '1c', '2a', '2b', '2c', '3a', '3b', '3c']. How can I do?
Easiest way would be to use the cartesian product macro available in the itertools crate
use itertools::iproduct; // 0.10.1
fn main() {
let x = vec!['1', '2', '3'];
let y = vec!['a', 'b', 'c'];
let product: Vec<String> = iproduct!(x, y)
.map(|(a, b)| format!("{}{}", a, b))
.collect();
println!("{:?}", product);
}
Playground
Here is how to do it with vanilla Rust iterators:
fn main() {
let x = vec!['1', '2', '3'];
let y = vec!['a', 'b', 'c'];
let product: Vec<String> = x
.iter()
.map(|&item_x| y
.iter()
.map(move |&item_y| [item_x, item_y]
.iter()
.collect()
)
)
.flatten()
.collect();
println!("{:?}", product);
}
Explanation
The easiest way to construct a String from two chars is to collect iterator over the chars:
let string: String = [item_x, item_y].iter().collect();
For each item in x we iterate over y and construct such string.
x.iter().map(|&item_x| y.iter.map(move |&item_y| ...));
We use pattern matching to get value in the map closure rather then references. Because of that and the fact that the char has Copy trait, we can move item_x into inner closure, resolving any lifetime issues.
As the result of the code above we get an iterator over iterators over Strings. To flatten that iterator, we use flatten method (who would think?). Then we collect the flat iterator into the resulting Vec.
Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bf2987ed96303a0db0f629884492011e
The existing answers make sense if your goal is to get the Cartesian product of two iterators. If you've got vectors or slices already though (like in the original question) you can do a little better:
fn main() {
let x = vec!['1', '2', '3'];
let y = vec!['a', 'b', 'c'];
let result: Vec<String> = product(&x, &y)
.map(|(a, b)| format!("{}{}", a, b))
.collect();
println!("{:?}", result)
}
fn product<'a: 'c, 'b: 'c, 'c, T>(
xs: &'a [T],
ys: &'b [T],
) -> impl Iterator<Item = (&'a T, &'b T)> + 'c {
xs.iter().flat_map(move |x| std::iter::repeat(x).zip(ys))
}
Playground
Any iterator based solution will necessarily require storing the full contents of the iterator somewhere, but if you already have the data in a vector or array you can use the known size to only store the indices instead.
I want to access the element next to the maximal one in a Vec<i32>. I'm looking for something like this:
let v = vec![1, 3, 2];
let it = v.iter().max_element();
assert_eq!(Some(&2), it.next());
In C++, I would go with std::max_element and then just increase the iterator (with or without bounds checking, depending on how adventurous I feel at the moment). The Rust max only returns a reference to the element, which is not good enough for my use case.
The only solution I came up with is using enumerate to get the index of the item - but this seems manual and cumbersome when compared to the C++ way.
I would prefer something in the standard library.
This example is simplified - I actually want to attach to the highest value and then from that point loop over the whole container (possibly with cycle() or something similar).
C++ iterators are not the same as Rust iterators. Rust iterators are forward-only and can only be traversed once. C++ iterators can be thought of as cursors. See What are the main differences between a Rust Iterator and C++ Iterator? for more details.
In order to accomplish your goal in the most generic way possible, you have to walk through the entire iterator to find the maximum value. Along the way, you have to duplicate the iterator each time you find a new maximum value. At the end, you can return the iterator corresponding to the point after the maximum value.
trait MaxElement {
type Iter;
fn max_element(self) -> Self::Iter;
}
impl<I> MaxElement for I
where
I: Iterator + Clone,
I::Item: PartialOrd,
{
type Iter = Self;
fn max_element(mut self) -> Self::Iter {
let mut max_iter = self.clone();
let mut max_val = None;
while let Some(val) = self.next() {
if max_val.as_ref().map_or(true, |m| &val > m) {
max_iter = self.clone();
max_val = Some(val);
}
}
max_iter
}
}
fn main() {
let v = vec![1, 3, 2];
let mut it = v.iter().max_element();
assert_eq!(Some(&2), it.next());
}
See also:
How can I add new methods to Iterator?
I actually want to attach to the highest value and then from that point loop over the whole container (possibly with cycle() or something similar).
In that case, I'd attempt to be more obvious:
fn index_of_max(values: &[i32]) -> Option<usize> {
values
.iter()
.enumerate()
.max_by_key(|(_idx, &val)| val)
.map(|(idx, _val)| idx)
}
fn main() {
let v = vec![1, 3, 2];
let idx = index_of_max(&v).unwrap_or(0);
let (a, b) = v.split_at(idx);
let mut it = b.iter().chain(a).skip(1);
assert_eq!(Some(&2), it.next());
}
See also:
What's the fastest way of finding the index of the maximum value in an array?
Using max_by_key on a vector of floats
What is the idiomatic way to get the index of a maximum or minimum floating point value in a slice or Vec in Rust?
Find the item in an array with the largest property
a simple solution is to use fold,
the following code produces "largest num is: 99"
let vv:Vec<i32> = (1..100).collect();
let largest = vv.iter().fold(std::i32::MIN, |a,b| a.max(*b));
println!("largest {} ", largest);
If all you want is the value of the item following the maximum, I would do it with a simple call to fold, keeping track of the max found so far and the corresponding next value:
fn main() {
let v = vec![1, 3, 2];
let nxt = v.iter().fold (
(None, None),
|acc, x| {
match acc {
(Some (max), _) if x > max => (Some (x), None),
(Some (max), None) => (Some (max), Some (x)),
(None, _) => (Some (x), None),
_ => acc
}
}
).1;
assert_eq!(Some(&2), nxt);
}
playground
Depending on what you want to do with the items following the max, a similar approach may allow you to do it in a single pass.
I am looking for the best way to go from String to Windows<T> using the windows function provided for slices.
I understand how to use windows this way:
fn main() {
let tst = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
let mut windows = tst.windows(3);
// prints ['a', 'b', 'c']
println!("{:?}", windows.next().unwrap());
// prints ['b', 'c', 'd']
println!("{:?}", windows.next().unwrap());
// etc...
}
But I am a bit lost when working this problem:
fn main() {
let tst = String::from("abcdefg");
let inter = ? //somehow create slice of character from tst
let mut windows = inter.windows(3);
// prints ['a', 'b', 'c']
println!("{:?}", windows.next().unwrap());
// prints ['b', 'c', 'd']
println!("{:?}", windows.next().unwrap());
// etc...
}
Essentially, I am looking for how to convert a string into a char slice that I can use the window method with.
The problem that you are facing is that String is really represented as something like a Vec<u8> under the hood, with some APIs to let you access chars. In UTF-8 the representation of a code point can be anything from 1 to 4 bytes, and they are all compacted together for space-efficiency.
The only slice you could get directly of an entire String, without copying everything, would be a &[u8], but you wouldn't know if the bytes corresponded to whole or just parts of code points.
The char type corresponds exactly to a code point, and therefore has a size of 4 bytes, so that it can accommodate any possible value. So, if you build a slice of char by copying from a String, the result could be up to 4 times larger.
To avoid making a potentially large, temporary memory allocation, you should consider a more lazy approach – iterate through the String, making slices at exactly the char boundaries. Something like this:
fn char_windows<'a>(src: &'a str, win_size: usize) -> impl Iterator<Item = &'a str> {
src.char_indices()
.flat_map(move |(from, _)| {
src[from ..].char_indices()
.skip(win_size - 1)
.next()
.map(|(to, c)| {
&src[from .. from + to + c.len_utf8()]
})
})
}
This will give you an iterator where the items are &str, each with 3 chars:
let mut windows = char_windows(&tst, 3);
for win in windows {
println!("{:?}", win);
}
The nice thing about this approach is that it hasn't done any copying at all - each &str produced by the iterator is still a slice into the original source String.
All of that complexity is because Rust uses UTF-8 encoding for strings by default. If you absolutely know that your input string doesn't contain any multi-byte characters, you can treat it as ASCII bytes, and taking slices becomes easy:
let tst = String::from("abcdefg");
let inter = tst.as_bytes();
let mut windows = inter.windows(3);
However, you now have slices of bytes, and you'll need to turn them back into strings to do anything with them:
for win in windows {
println!("{:?}", String::from_utf8_lossy(win));
}
This solution will work for your purpose. (playground)
fn main() {
let tst = String::from("abcdefg");
let inter = tst.chars().collect::<Vec<char>>();
let mut windows = inter.windows(3);
// prints ['a', 'b', 'c']
println!("{:?}", windows.next().unwrap());
// prints ['b', 'c', 'd']
println!("{:?}", windows.next().unwrap());
// etc...
println!("{:?}", windows.next().unwrap());
}
String can iterate over its chars, but it's not a slice, so you have to collect it into a vec, which then coerces into a slice.
You can use itertools to walk over windows of any iterator, up to a width of 4:
extern crate itertools; // 0.7.8
use itertools::Itertools;
fn main() {
let input = "日本語";
for (a, b) in input.chars().tuple_windows() {
println!("{}, {}", a, b);
}
}
See also:
Are there equivalents to slice::chunks/windows for iterators to loop over pairs, triplets etc?
I have a vector where the element is a (String, String). How can I randomly pick one of these elements?
You want the rand crate, specifically the choose method.
use rand::seq::SliceRandom; // 0.7.2
fn main() {
let vs = vec![0, 1, 2, 3, 4];
println!("{:?}", vs.choose(&mut rand::thread_rng()));
}
Using choose_multiple:
use rand::seq::SliceRandom; // 0.7.2
fn main() {
let samples = vec!["hi", "this", "is", "a", "test!"];
let sample: Vec<_> = samples
.choose_multiple(&mut rand::thread_rng(), 1)
.collect();
println!("{:?}", sample);
}
Another choice for weighted sampling that is already included in the rand crate is WeightedIndex, which has an example:
use rand::prelude::*;
use rand::distributions::WeightedIndex;
let choices = ['a', 'b', 'c'];
let weights = [2, 1, 1];
let dist = WeightedIndex::new(&weights).unwrap();
let mut rng = thread_rng();
for _ in 0..100 {
// 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c'
println!("{}", choices[dist.sample(&mut rng)]);
}
let items = [('a', 0), ('b', 3), ('c', 7)];
let dist2 = WeightedIndex::new(items.iter().map(|item| item.1)).unwrap();
for _ in 0..100 {
// 0% chance to print 'a', 30% chance to print 'b', 70% chance to print 'c'
println!("{}", items[dist2.sample(&mut rng)].0);
}
If you want to choose more than one element then the random_choice crate may be right for you:
extern crate random_choice;
use self::random_choice::random_choice;
fn main() {
let mut samples = vec!["hi", "this", "is", "a", "test!"];
let weights: Vec<f64> = vec![5.6, 7.8, 9.7, 1.1, 2.0];
let number_choices = 100;
let choices = random_choice().random_choice_f64(&samples, &weights, number_choices);
for choice in choices {
print!("{}, ", choice);
}
}
If you also want to remove the chosen element, here's one way to do that (using the rand crate):
let mut vec = vec![0,1,2,3,4,5,6,7,8,9];
let index = (rand::random::<f32>() * vec.len() as f32).floor() as usize;
let value = vec.remove( index );
println!("index: {} value: {}", index, value);
println!("{:?}", vec);
Rust Playground
remove(index) removes that value at index (shifting all the elements after it to the left) and the returns the value that was at index (docs).
Another way of getting a random value is via the indexing method using rng.gen_range and vec.get(). This also prevents the borrowing of the value (which occurs with the vec.choose() method)
fn main() {
let mut rng = rand::thread_rng();
let my_strings : Vec<&str> = vec!["a", "b", "c"];
let random_string_index: usize = rng.gen_range(0..my_strings.len());
let string = my_strings[random_string_index];
println!("{:?}", string);
}