Problems trying to get intersection of a Vector - rust

I am having a problem whilst trying to get the intersection of two Vectors.
impl Solution {
pub fn intersection(nums: Vec<Vec<i32>>) -> Vec<i32> {
// Intended strategy:
// Store the first element into an intersect_result
// Iterate over the remaining elements for each element:
// Determine the intersection of the current element and the intersect result
// set intersect result to this.
// Sort the intersect result
// Return the intersect result back to the caller.
let len:i32 = nums.len() as i32;
let intersect_result:Vec<i32> = nums[0].clone();
for i in 1..len{
println!("i is: {}", i);
let temp_vec:Vec<i32> = nums[i as usize].clone();
// find the intersection of the current element with the intersect result
let unique_a:HashSet<i32> = temp_vec.into_iter().collect();
let unique_b:HashSet<i32> = intersect_result.clone().into_iter().collect();
intersect_result = unique_a.intersection(&unique_b).collect::<Vec<_>>();
}
vec![]
}
}
The error message I get is:
= note: expected struct `Vec<i32>`
found struct `Vec<&i32>`
This happens in the call unique_a.intersection().
Any thoughts guys?

You can add a map(|i| *i) in the iterator chain that causes the error:
intersect_result = unique_a.intersection(&unique_b).map(|i| *i).collect::<Vec<_>>();
When fixing this, the code also seems to work as intended. I think there are a few improvements possible (probably more, but these immediately tracked my attention):
use hashbrown::HashSet;
pub fn intersection(nums: Vec<Vec<i32>>) -> Vec<i32> {
let mut intersect_result: Vec<i32> = nums[0].clone();
for temp_vec in nums {
let unique_a: HashSet<i32> = temp_vec.into_iter().collect();
intersect_result = unique_a
.intersection(&intersect_result.into_iter().collect())
.map(|i| *i)
.collect::<Vec<_>>();
}
intersect_result
}
fn main() {
let a = vec![1, 2, 3];
let b = vec![2, 3, 4];
let c = vec![3, 4, 5];
let v = vec![a, b, c];
let res = intersection(v);
println!("res: {:?}", res);
}

Related

How can I iterate over a sequence multiple times within a function?

I have a function that I would like to take an argument that can be looped over. However I would like to loop over it twice. I tried using the Iterator trait however I can only iterate over it once because it consumes the struct when iterating.
How should I make it so my function can loop twice? I know I could use values: Vec<usize> however I would like to make it generic over any object that is iterable.
Here's an example of what I would like to do: (Please ignore what the loops are actually doing. In my real code I can't condense the two loops into one.)
fn perform<'a, I>(values: I) -> usize
where
I: Iterator<Item = &'a usize>,
{
// Loop one: This works.
let sum = values.sum::<usize>();
// Loop two: This doesn't work due to `error[E0382]: use of moved value:
// `values``.
let max = values.max().unwrap();
sum * max
}
fn main() {
let v: Vec<usize> = vec![1, 2, 3, 4];
let result = perform(v.iter());
print!("Result: {}", result);
}
You can't iterate over the same iterator twice, because iterators are not guaranteed to be randomly accessible. For example, std::iter::from_fn produces an iterator that is most definitely not randomly accessible.
As #mousetail already mentioned, one way to get around this problem is to expect a Cloneable iterator:
fn perform<'a, I>(values: I) -> usize
where
I: Iterator<Item = &'a usize> + Clone,
{
// Loop one: This works.
let sum = values.clone().sum::<usize>();
// Loop two: This doesn't work due to `error[E0382]: use of moved value:
// `values``.
let max = values.max().unwrap();
sum * max
}
fn main() {
let v: Vec<usize> = vec![1, 2, 3, 4];
let result = perform(v.iter());
println!("Result: {}", result);
}
Result: 40
Although in your specific example, I'd compute both sum and max in the same iteration:
fn perform<'a, I>(values: I) -> usize
where
I: Iterator<Item = &'a usize>,
{
let (sum, max) = values.fold((0, usize::MIN), |(sum, max), &el| {
(sum + el, usize::max(max, el))
});
sum * max
}
fn main() {
let v: Vec<usize> = vec![1, 2, 3, 4];
let result = perform(v.iter());
println!("Result: {}", result);
}
Result: 40

How do I empty a slice in a RefMut<&mut [u8]>?

If I wanted to "empty" a slice normally, I could do something like this:
let mut data: &[u8] = &[1, 2, 3];
data = &[];
But I'm using a library that returns a RefMut<&mut [u8]>, and if I try to reset it the same way:
let mut data: RefMut<&mut [u8]> = account.data.borrow_mut();
data = &[];
I get told I need:
expected struct `RefMut`, found `&[_; 0]`
I try something like this:
let mut data: RefMut<&mut [u8]> = account.data.borrow_mut();
let cleared: &mut [u8] = &mut [];
let c = RefCell::new(cleared);
data = c.borrow_mut();
But then c is dropped while still borrowed. Am I going about this the wrong way?
You can use the dereference operator to write back to the RefCell.
let refcell: RefCell<&[u8]> = RefCell::new(&[1, 2, 3]);
{
let mut data = refcell.borrow_mut();
*data = &[];
// or equivalently, *refcell.borrow_mut() = &[];
}
println!("{:?}", refcell); // RefCell { value: [] }

Is there a way to shuffle two or more lists in the same order?

I want something like this pseudocode:
a = [1, 2, 3, 4];
b = [3, 4, 5, 6];
iter = a.iter_mut().zip(b.iter_mut());
shuffle(iter);
// example shuffle:
// a = [2, 4, 3, 1];
// b = [4, 6, 5, 3];
More specifically, is there some function which performs like:
fn shuffle<T>(iterator: IterMut<T>) { /* ... */ }
My specific case is trying to shuffle an Array2 by rows and a vector (array2:Lndarray:Array2<f32>, vec:Vec<usize>).
Specifically array2.iter_axis(Axis(1)).zip(vec.iter()).
Shuffling a generic iterator in-place is not possible.
However, it's pretty easy to implement shuffling for a slice:
use rand::Rng;
pub fn shufflex<T: Copy>(slice: &mut [T]) {
let mut rng = rand::thread_rng();
let len = slice.len();
for i in 0..len {
let next = rng.gen_range(i, len);
let tmp = slice[i];
slice[i] = slice[next];
slice[next] = tmp;
}
}
But it's also possible to write a more general shuffle function that works on many types:
use std::ops::{Index, IndexMut};
use rand::Rng;
pub fn shuffle<T>(indexable: &mut T)
where
T: IndexMut<usize> + Len + ?Sized,
T::Output: Copy,
{
let mut rng = rand::thread_rng();
let len = indexable.len();
for i in 0..len {
let next = rng.gen_range(i, len);
let tmp = indexable[i];
indexable[i] = indexable[next];
indexable[next] = tmp;
}
}
I wrote a complete example that also allows shuffling across multiple slices in the playground.
EDIT: I think I misunderstood what you want to do. To shuffle several slices in the same way, I would do this:
use rand::Rng;
pub fn shuffle<T: Copy>(slices: &mut [&mut [T]]) {
if slices.len() > 0 {
let mut rng = rand::thread_rng();
let len = slices[0].len();
assert!(slices.iter().all(|s| s.len() == len));
for i in 0..len {
let next = rng.gen_range(i, len);
for slice in slices.iter_mut() {
let tmp: T = slice[i];
slice[i] = slice[next];
slice[next] = tmp;
}
}
}
}
To shuffle in the same order, you can first remember the order and then reuse it for every shuffle. Starting with the Fisher-Yates shuffle from the rand crate:
fn shuffle<R>(&mut self, rng: &mut R)
where R: Rng + ?Sized {
for i in (1..self.len()).rev() {
self.swap(i, gen_index(rng, i + 1));
}
}
It turns out that we need to store random numbers between 0 and i + 1 for each i between 1 and the length of the slice, in reverse order:
// create a vector of indices for shuffling slices of given length
let indices: Vec<usize> = {
let mut rng = rand::thread_rng();
(1..slice_len).rev()
.map(|i| rng.gen_range(0, i + 1))
.collect()
};
Then we can implement a variant of shuffle where, instead of generating new random numbers, we pick them up from the above list of random indices:
// shuffle SLICE taking indices from the provided vector
for (i, &rnd_ind) in (1..slice.len()).rev().zip(&indices) {
slice.swap(i, rnd_ind);
}
Putting the two together, you can shuffle multiple slices in the same order using a method like this (playground):
pub fn shuffle<T>(slices: &mut [&mut [T]]) {
if slices.len() == 0 {
return;
}
let indices: Vec<usize> = {
let mut rng = rand::thread_rng();
(1..slices[0].len())
.rev()
.map(|i| rng.gen_range(0, i + 1))
.collect()
};
for slice in slices {
assert_eq!(slice.len(), indices.len() + 1);
for (i, &rnd_ind) in (1..slice.len()).rev().zip(&indices) {
slice.swap(i, rnd_ind);
}
}
}

Why do I get "no method named `join` found for type `[usize]` in the current scope"?

fn example(books: Vec<usize>, n_books: usize) {
let fbooks = books[0..n_books].join(" ");
}
error[E0599]: no method named `join` found for type `[usize]` in the current scope
--> src/lib.rs:2:36
|
2 | let fbooks = books[0..n_books].join(" ");
| ^^^^ method not found in `[usize]`
I tried mapping usize to String, collecting into Vec and some more random stuff. I don't understand what's going on.
TLDR:
Since map() transforms one iterator into another iterator, you should provide an iterator first.
Try this:
fn example(books: Vec<usize>, n_books: usize) -> String {
books[0..n_books]
.iter()
.map(|u| u.to_string())
.collect::<Vec<_>>()
.join(" ")
}
fn main() {
let books: Vec<usize> = vec![1, 2, 3];
let n_books: usize = 2;
let result = example(books, n_books);
println!("{}", result); //"1 2"
}
Notes:
You should not join the usize vector items with &str type. You need to convert usize to string first then join it:
map(|u| u.to_string())
The standard library's join is defined only for slices, so the following code works:
let books: &[_] = &["1", "2", "3"];
let n_books: usize = 2;
let result = books[0..n_books].join(" ");
println!("{}", result); // "1 2"
Edit:
From your comment:
What's the difference using take(n) or a subscript operator (re-slicing books[0..n_books])
A slice is a type composed of a length and a pointer to a memory.
You may use .take(n_books) instead of re-slicing, which is an iterator that only iterates over the first n iterations of iter, try this:
let books: Vec<usize> = vec![1, 2, 3];
let n_books: usize = 2;
let result = books
.iter()
.take(n_books)
.map(|u| u.to_string())
.collect::<Vec<_>>()
.join(" ");
println!("{}", result); //"1 2"

What is the idiomatic way to pop the last N elements in a mutable Vec?

I am contributing Rust code to RosettaCode to both learn Rust and contribute to the Rust community at the same time. What is the best idiomatic way to pop the last n elements in a mutable Vec?
Here's roughly what I have written but I'm wanting to see if there's a better way:
fn main() {
let mut nums: Vec<u32> = Vec::new();
nums.push(1);
nums.push(2);
nums.push(3);
nums.push(4);
nums.push(5);
let n = 2;
for _ in 0..n {
nums.pop();
}
for e in nums {
println!("{}", e)
}
}
(Playground link)
I'd recommend using Vec::truncate:
fn main() {
let mut nums = vec![1, 2, 3, 4, 5];
let n = 2;
let final_length = nums.len().saturating_sub(n);
nums.truncate(final_length);
println!("{:?}", nums);
}
Additionally, I
used saturating_sub to handle the case where there aren't N elements in the vector
used vec![] to construct the vector of numbers easily
printed out the entire vector in one go
Normally when you "pop" something, you want to have those values. If you want the values in another vector, you can use Vec::split_off:
let tail = nums.split_off(final_length);
If you want access to the elements but do not want to create a whole new vector, you can use Vec::drain:
for i in nums.drain(final_length..) {
println!("{}", i)
}
An alternate approach would be to use Vec::drain instead. This gives you an iterator so you can actually use the elements that are removed.
fn main() {
let mut nums: Vec<u32> = Vec::new();
nums.push(1);
nums.push(2);
nums.push(3);
nums.push(4);
nums.push(5);
let n = 2;
let new_len = nums.len() - n;
for removed_element in nums.drain(new_len..) {
println!("removed: {}", removed_element);
}
for retained_element in nums {
println!("retained: {}", retained_element);
}
}
The drain method accepts a RangeArgument in the form of <start-inclusive>..<end-exclusive>. Both start and end may be omitted to default to the beginning/end of the vector. So above, we're really just saying start at new_len and drain to the end.
You should take a look at the Vec::truncate function from the standard library, that can do this for you.
(playground)
fn main() {
let mut nums: Vec<u32> = Vec::new();
nums.push(1);
nums.push(2);
nums.push(3);
nums.push(4);
nums.push(5);
let n = 2;
let new_len = nums.len() - n;
nums.truncate(new_len);
for e in nums {
println!("{}", e)
}
}

Resources