In a Rust function, I have two different collection types that both contain strings. I need to iterate over one of them with a loop, but the iterator types are different. How would I bring both iterators to a common denominator?
use std::collections::{HashMap, HashSet};
fn main() {
run(true);
run(false);
}
fn run(some_argument: bool) {
let set: HashSet<String> = (0..4).map(|v| v.to_string()).collect();
let map: HashMap<String, i32> = (5..9).map(|v| (v.to_string(), v)).collect();
// this should be a generic non-consuming iterator over &String (or &str?) values
let iter = if some_argument {
&set.iter()
} else {
&map.keys()
};
for v in iter {
println!("{v}");
}
}
P.S. Bonus: what if one of the collection types stores &str
instead of String
- can that be done without significant reallocations/complexities?
There are 2 solutions which can achieve similar functionality to what you are looking for
fn run(some_argument: bool) {
let set: HashSet<String> = (0..4).map(|v| v.to_string()).collect();
let map: HashMap<String, i32> = (5..9).map(|v| (v.to_string(), v)).collect();
let iter: Box<dyn Iterator<Item=&String>> = if some_argument {
Box::new(set.iter())
} else {
Box::new(map.keys())
};
for v in iter {
println!("{v}");
}
}
fn run(some_argument: bool) {
let set: HashSet<String> = (0..4).map(|v| v.to_string()).collect();
let map: HashMap<String, i32> = (5..9).map(|v| (v.to_string(), v)).collect();
if some_argument {
print(&mut set.iter());
} else {
print(&mut map.keys());
}
}
fn print(iter: &mut dyn Iterator<Item=&String>) {
for v in iter {
println!("{v}");
}
}