Hello! I was trying to build an iterator incrementally but I found myself in a really intricate case and I'm not sure how to make the code less if-else heavy, here an example of what I'm trying to do:
#[derive(PartialEq, Eq, Debug)]
pub enum TypeA {
A,
B,
C,
}
#[derive(PartialEq, Eq, Debug)]
pub enum TypeB {
BA,
BB,
BC,
}
#[derive(Debug)]
pub struct Example {
a: TypeA,
b: TypeB,
}
impl Example {
fn new(a: TypeA, b: TypeB) -> Self {
Self { a, b }
}
}
pub struct CreatureSearchBuilder {
pub values: Vec<Example>,
pub a: Option<TypeA>,
pub b: Option<TypeB>,
}
impl CreatureSearchBuilder {
pub fn new(values: Vec<Example>) -> Self {
Self {
values,
a: None,
b: None,
}
}
pub fn search(&self) -> Vec<&Example> {
if let Some(a) = &self.a {
if let Some(b) = &self.b {
self.values
.iter()
.filter(|v| v.a == *a && v.b == *b)
.collect()
} else {
self.values.iter().filter(|v| v.a == *a).collect()
}
} else if let Some(b) = &self.b {
self.values.iter().filter(|v| v.b == *b).collect()
} else {
vec![]
}
}
}
pub fn main() {
let values = vec![
Example::new(TypeA::A, TypeB::BA),
Example::new(TypeA::B, TypeB::BB),
Example::new(TypeA::C, TypeB::BC),
];
let mut search = CreatureSearchBuilder::new(values);
search.b = Some(TypeB::BB);
let results = search.search();
println!("{:?}", results);
}
The central point here is the search function, I have to duplicate the code multiple times to filter and collect and adding new filter values this is going to be worst and worst with many if else statements.
This is the way I was trying to write it, using a variable to keep track of the "new" iterator:
let mut iter = values.iter();
if let Some(t) = test_1 {
iter = iter.filter(|v| v.a = t);
}
if let Some(t) = test_2 {
iter = iter.filter(|v| v.b = t);
}
iter.collect()
but I was unlucky with the approach even if it was the best way I can think of because of the temporary values (test_1 and test_2) that will be used by the collect function at the end but dropped after the if block are finished.
I tried to box the predicate but that was unlucky as well and still ugly considering that I still have to have the if statements.
Is there any other way I can write that search function with the approach I described?
Thank you