Reputation: 7045
Is there a way to convert a String
to some other type dynamically? I have a vector of values in the format key:type:value
that I'd like to convert to key value pairs where the value has been converted to the correct type. In this case the types map as: i=i64
, and f=f64
.
So far I have this:
fn main() {
let arr: Vec<String> = vec!["A:i:49".to_string(), "B:f:0.1374".to_string()];
let tup: Vec<_> = arr
.iter()
.map(|s| s.split(":").collect::<Vec<&str>>())
.collect();
println!("Arr: {:#?}", arr);
println!("Tup: {:?}", tup)
}
// Arr: [
// "A:i:49",
// "B:f:0.1374",
// ]
// Tup: [["A", "i", "49"], ["B", "f", "0.1374"]]
Looking to acheive something like:
[("A", 49), ("B", 0.1374)]
I've looked at generics/implementations but cannot work out what to do.
Note: any vec may have any key, so the next set could be ["A:i:99", "C:i:0"]
, types are limited to integers, floats, and strings.
Upvotes: 0
Views: 217
Reputation: 1856
A solution using Enum wrapper type
#[derive(Debug)]
enum Value {
IntVal(i32),
FloatVal(f64),
}
let tup: Vec<_> = arr
.iter()
.map(|s| {
let mut values = s.split(":");
let first_tk = values.next().unwrap();
let second_tk = values.next().unwrap();
let third_tk = values.next().unwrap();
let value = match second_tk {
"i" => Value::IntVal(FromStr::from_str(third_tk).expect("Invalid int")),
"f" => Value::FloatVal(FromStr::from_str(third_tk).expect("invalid float")),
_ => panic!("unexpected pattern {}", second_tk),
};
(first_tk, value)
})
.collect();
playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0e8ae249e91cb0055f09c9b1bd96ebde
Note: You need to do proper error handling and current code just panics whenever it encounters unexpected value. You need to use Result type for that. Also, you could explore FromStr trait to parse from string
Upvotes: 2