How to slice to a particular element in a Vec? - rust

What is the best way to slice a Vec to the first occurrence of a particular element?
A naive method demonstrating what I want to do:
fn main() {
let v = vec![1, 2, 3, 4, 5, 6];
let to_num = 5;
let mut idx = 0;
for x in &v {
if x != &to_num {
idx += 1
} else {
break;
}
}
let slice = &v[..idx];
println!("{:?}", slice); //prints [1, 2, 3, 4]
}
^ on the Rust playground

You can use <[T]>::split():
let slice = v.split(|x| *x == to_num).next().unwrap();
Playground.

Related

how to convert Option<&u8> to u8

i want to convert Option<&u8> to u8 so i will be able to print it
my code:
fn main() {
let v : Vec<u8> = vec![1, 2, 3, 4, 5];
let out_of_range = &v[100];
let out_of_range = v.get(100);
match out_of_range{
Some(&u8) => println!("data out of range: {}", out_of_range),
None => println!("bruh"),
}
}
Your match statement needs the introduction of a binding, not a type (the &u8 you used was not expected here).
Here Some(val) matches with something which is an Option<&u8>, thus val is a binding to the embedded &u8 (if not None, of course).
The example explicitly dereferences val as an illustration, and highlights the fact that val is not an u8 but a reference, but it's not required for the following operation (printing).
fn main() {
let v: Vec<u8> = vec![1, 2, 3, 4, 5];
for idx in [2, 20, 4] {
let at_index = v.get(idx);
match at_index {
Some(val) => {
// val has type &u8
let copy_of_val = *val; // not required, just for the example
println!("at {} --> {}", idx, copy_of_val);
}
None => println!("no value at {}", idx),
}
}
}

Cannot borrow `counts` as immutable because it is also borrowed as mutable

I'm getting this error
error[E0502]: cannot borrow `counts` as immutable because it is also borrowed as mutable
--> src/main.rs:13:64
|
13 | counts.entry(x).or_insert(cmp::max(current_count, *counts.get(&x).unwrap()));
| --------------- --------- ^^^^^^^^^^^^^^ immutable borrow occurs here
| | |
| | mutable borrow later used by call
| mutable borrow occurs here
but I can't seem to understand what's wrong despite having seen a few other questions asking about the same error and they are using slice instead of dealing with a HashMap like here.
The 2nd argument of cmp::max has to be a value, but I cant figure out how to make use of an mutable borrow here as suggested by the compiler.
use std::collections::HashMap;
use std::cmp;
fn main() {
let data: Vec<u8> = vec![1,1,3,1,1];
let mut counts = HashMap::new();
let mut current_count = 0;
for (i, &x) in data.iter().enumerate() {
if i > 0 {
if x == data[i-1] {
current_count += 1;
counts.entry(x).or_insert(cmp::max(current_count, *counts.get(&x).unwrap()));
} else {
current_count = 0;
}
}
}
println!("{:?}", counts);
}
#BallpointBen I think this might work, but not sure if this is a good way.
for (i, &x) in data.iter().enumerate() {
if i > 0 {
if x == data[i-1] {
current_count += 1;
counts.entry(x).or_insert(1);
counts.insert(x, cmp::max(current_count, counts[&x]));
} else {
current_count = 0;
}
}
}
HashMap::entry() borrows the map mutably for the whole life of the returned Entry. You cannot use the map until you finish with the entry.
The fix is simple - first retrieve the value into a variable, then call entry():
let v = *counts.get(&x).unwrap();
counts
.entry(x)
.or_insert(cmp::max(current_count, v));
You cannot use or_insert_with() by that, which would be preferred, but you didn't use it anyway.
However, what you're trying to do is not good: when will your or_insert() be needed? Only when there is no value associated with this key in the map, so trying to get().unwrap() it is always going to panic!
Here is a solution that meshes well with the type system. We append a None to the end of the iterator to signal that we're done (roughly equivalent to an if i == my_vec.len()-1 check but without needing a Vec)
use std::collections::HashMap;
use std::hash::Hash;
fn longest_run<T: Hash + Eq>(items: impl IntoIterator<Item = T>) -> HashMap<T, usize> {
let mut runs = HashMap::new();
let mut items = items.into_iter();
let mut prev = match items.next() {
Some(x) => x,
None => return runs,
};
let mut curr_count = 1;
for item in items.map(Some).chain(std::iter::once(None)) {
if let Some(item) = item {
if item == prev {
curr_count += 1;
} else {
let prev_count = runs.entry(prev).or_insert(1);
*prev_count = (*prev_count).max(curr_count);
curr_count = 1;
}
prev = item;
} else {
let prev_count = runs.entry(prev).or_insert(1);
*prev_count = (*prev_count).max(curr_count);
// Redundant, but needed to tell the compiler it's
// ok to move prev into `entry` without
// reinitializing it, as we won't need it again
break;
}
}
runs
}
fn main() {
for v in vec![
vec![],
vec![1],
vec![1, 1, 1, 1, 1],
vec![1, 2],
vec![1, 1, 2, 1],
vec![1, 1, 2, 1, 1, 1, 1, 2, 2, 2],
vec![1, 1, 1, 1, 1, 2, 3, 1, 1, 2, 2, 3, 3],
] {
println!("{:?}: {:?}", v, longest_run(v.iter().copied()));
}
}
Prints
[]: {}
[1]: {1: 1}
[1, 1, 1, 1, 1]: {1: 5}
[1, 2]: {2: 1, 1: 1}
[1, 1, 2, 1]: {1: 2, 2: 1}
[1, 1, 2, 1, 1, 1, 1, 2, 2, 2]: {2: 3, 1: 4}
[1, 1, 1, 1, 1, 2, 3, 1, 1, 2, 2, 3, 3]: {2: 2, 3: 2, 1: 5}

How to swap contents of two indices of a Vec inside a loop?

I'm trying to swap the elements inside a loop.
fn foo(nums: &mut Vec<i32>) {
let mut i: usize = 0;
for (j, n) in nums.iter_mut().enumerate() {
if n != &0 {
// swap nums[i] and nums[j];
i = i + 1;
}
}
}
But I keep getting the same error (along cannot borrow mutable nums multiple times). What am I doing wrong?
Maybe this is not exactly what you want but it may help.
fn main() {
let mut vec = vec![1, 0, 3, 4];
let mut i = 0;
for j in 0..vec.len() {
if vec[j] != 0 {
vec.swap(i, j);
i = i + 1;
}
}
println!("{:?}", vec);
}
Rust Playground

How to idiomatically check if a 2-dimensional vector is a table? [duplicate]

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()

Check if length of all vectors is the same in Rust

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()

Resources