2

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

10
  • How your Question structs are produced ? Commented Oct 25, 2019 at 19:23
  • Is it important that v be a Vec<&mut Question> with references to local variables? Why not just Vec<Question>? Commented Oct 25, 2019 at 19:32
  • It looks like your question might be answered by the answers of How to init a Rust vector with a generator function?. If not, please edit your question to explain the differences. Otherwise, we can mark this question as already answered. Commented Oct 25, 2019 at 20:18
  • 1
    I don't understand why you say you need Vec<&mut Question>. This complicates things because something has to own the Questions. What's wrong with just Vec<Question>? Commented Oct 26, 2019 at 18:29
  • 2
    Maybe you should focus on creating Question structs without hardcoding. You can use json format(load external JSON file or embed as JSON string) then deserialize as Vec<Question>. If you still want to write as hardcoded then you can create your struct with a constructor, you can push the question while it constructs like this Commented Oct 26, 2019 at 18:45

2 Answers 2

3

The problem is because you don't have any data structure that contains the Questions -- 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 Questions 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();
Sign up to request clarification or add additional context in comments.

Comments

0

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);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.