Reputation: 33
I am trying to find an elegant way to fill a vector of struct elements with a loop or logic instead of writing one .push()
for every element I create.
The struct
element is a question with many more fields than in the following example and the instances need to be mutable because they are modified by user input :
struct Question {
id: usize,
question: String,
}
fn main() {
//A large and growing list of questions
let mut q0 = Question {
id: 0,
question: String::from("A field I fill in manually"),
};
// .
// .
// .
let mut q100 = Question {
id: 100,
question: String::from("Another field, each one is different"),
};
let total_questions: usize = 100;
let mut w: Vec<String> = Vec::new();
for a in 0..total_questions {
let s = format!("q{}", a);
w.push(s);
}
//w contains ["q0", "q1", ..., "q100"] but is of type std::string::String
let mut v: Vec<&mut Question> = Vec::new();
//Expects type struct `main::Question`
//I would like to avoid :
v.push(&mut q0);
v.push(&mut q1);
// .
// .
// .
v.push(&mut q100);
}
I am not sure that in my example the w: Vec<String>
is of any use.
I have looked into .collect()
but could not understand how to utilize it in my case.
I'd be happy to be pointed towards a similar question if this is a duplicate I have not found one.
Edit : I have changed the structs string content as it was misleading. They each contain Strings that are unique and cannot be generated. I also realized that Stack Overflow automatically included this in a some_fn()
function when we are actually inside main()
Upvotes: 2
Views: 4880
Reputation: 28005
The problem is because you don't have any data structure that contains the Question
s -- you just have 100+ independent local variables -- it's not possible to iterate over them to fill the Vec
. You can fix this by putting all the Question
s in a Vec<Question>
as you create them. Here's an example:
let mut v: Vec<Question> = vec![
Question {
id: 0,
question: String::from("Q0"),
},
// ...
Question {
id: 100,
question: String::from("Q100"),
},
];
In fact, once you do this you probably don't need the Vec<&mut Question>
at all, since you can mutate the questions directly by indexing v
. However, if you do need the vector of references for some reason, you can create it by collecting an iterator:
let v_refs: Vec<&mut Question> = v.iter_mut().collect();
Upvotes: 3
Reputation: 9416
If you can generate your Question
object with a function you can use an iterator. Here is an example which just generates numbered Question
objects out of a numeric range:
struct Question {
id: usize,
question: String,
}
fn main() {
let v: Vec<Question> = (0..10)
.map(|x| Question {
id: x,
question: "Q".to_string() + &x.to_string(),
})
.collect();
for x in &v {
println!("{}: {}", x.id, x.question);
}
}
Here is an example where you get the strings from an array of strings:
struct Question<'a> {
id: usize,
question: &'a str,
}
const QUESTIONS: [&str; 3] = ["A", "B", "C"];
fn main() {
let v: Vec<Question> = (0..questions.len())
.map(|x| Question {
id: x,
question: questions[x],
})
.collect();
for x in &v {
println!("{}: {}", x.id, x.question);
}
}
Upvotes: 0