How to borrow values from one vector inside a struct's field?

I have a struct that has two vectors as its fields like this:

struct Words<'a> {
    words: Vec<String>,
    clean_words: Vec<&'a str>,
}

I'm still new and I'm trying new stuff to get comfortable with Rust's idioms. So for this one, the idea is that I read a file with words and store all the words inside words vec then I call another function which evaluates if a word satisfies certain requirements to be used and if it does I want to store a reference to that word in a vec called clean_words. But the challenge is that because I have to borrow mutably from the words and indicate the lifetime, whole structs remain borrowed mutably until it's dropped (pretty much throughout the program) and I can't iterate over the clean_words.

Here's the example code

I'm on mobile, so you won't get too long of an answer from me. The keyword so search for us "self-referential" structs, something that Rust doesn't really support at all. There are a few crates that offer some support like e. g. ouroboros, otherwise you'd need unsafe code.

However, depending on your use case you'll definitely want to check if you have any need to bundle the two Vecs as a single struct at all, in the first place.

Looking at your code shortly, you could remove the words field and instead pass some words: &'a [String] as an extra argument to the relevant method. Or you change the struct so that the words field stays but gets this type words: &'a [String] so that the word selector struct still has to be created without owning its own words vector, but you don't need to pass the reference again for each method call that might need it.

Alternatives include

  • Just store words (Vec<String>) and clean_words (Vec<&str>) separately
  • Use Vec::retain to filter the list of stored words after loading
  • Filter when loading words and just don't store unclean words at all
  • Use iterators and filter dynamically
  • Sort the words by cleanliness and use a &[String] for clean words (stored separately)

I'll add one more option if you really want both in the same struct, which is to store a Vec of usize indices to the clean words.

3 Likes

This also works well combined with iteration.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.