Siriusmart
Siriusmart

Reputation: 197

Get Data From Structs With String Key, And Struct to Array

Is it possible to get a value from a struct using a string key? Like this:

struct Messages {
    greetings: String,
    goodbyes: String
}

impl Structure {
    fn new() -> Structure{
        Messages {
            greetings: String::from("Hello world"),
            goodbyes: String::from("Bye!")
    }
}

fn main() {
    let messages = Messages::new();
    // now how do I print it out with a string key?
    println!("{}",messages["greetings"]); // prints "Hello world"

    // and can I even turn a struct into an array? Function name is made up
    let arr = Struct::to_array(messages);
}

Pls help thz

Upvotes: 1

Views: 2414

Answers (1)

cameron1024
cameron1024

Reputation: 10216

In short, no, this is not possible. The names of your fields aren't necessarily available at runtime to perform such a check. However, there are other ways to achieve similar results:

  • use a HashMap<String, String>
  • write a function to do it:
impl MyStruct {
  pub fn get_field(&self, key: String) -> &str {
    if key == 'field1' {
      self.field1
    } else if ...
  }
}
  • Write a derive macro to generate the above function automatically (https://crates.io/crates/field_names might be a useful starting point for how you might go about writing a derive macro)

Or solve it a different way

This pattern is not well supported in Rust, especially compared to more dynamic languages like JavaScript. A problem many new Rust learners face is solving problems "the Rust way".

It's not 100% clear from your comment, but it sounds like your struct is representing a tic-tac-toe board and looks something like this:

struct Board {
  top_right: String,
  top_middle: String,
  top_left: String,
  // etc...
}

While this works, there are much better ways of doing this. For example, you could represent each tile with an enum instead of a String, and you could also use an Vec (similar to arrays/lists from other languages) to store that data:

enum Tile {
  Empty,
  Cross,
  Circle,
}

struct Board {
  tiles: Vec<Tile>,
}

impl Board {
  pub fn print(&self) {
    for tile in self.tiles {
      println!("{}", match tile {
        Tile::Empty => " ",        
        Tile::Cross => "X"
        Tile::Circle => "O",
      });  
    }
  }
}

Upvotes: 2

Related Questions