Convertir cadena de valor clave par en HashMap en una línea
Tengo una cadena con contenidos como los siguientes:
key1:value1 key2:value2 key3:value3 ...
Quiero terminar con un HashMap<&str, &str>
(o equivalente), que mapea las teclas y los valores de la cadena (por ejemplo, una búsqueda precipitada de "key1" debe devolver "valor1").
Actualmente, puedo llenar fácilmente el HashMap con lo siguiente:
let mut hm = HashMap::new();
for item in my_string.split_ascii_whitespace() {
let splits = item.split(":").collect::>();
hm.insert(splits[0], splits[1]);
}
Sin embargo, ¿qué pasaría si quisiera hacerlo en una línea (incluso a un costo de legibilidad, para "código golf"-ish fines)? Sé cómo hacer esto con un HashSet
, así que imagino que parecería algo similar; tal vez algo así (que en realidad no compila):
let hm: HashMap<&str, &str> = HashMap::from_iter(my_string.split_ascii_whitespace().map(|s| s.split(":").take(2).collect::>()));
He probado diferentes combinaciones de cosas similares a las anteriores, pero no puedo encontrar algo que realmente compila.
Pregunta hecha hace 3 años, 4 meses, 27 días - Por bytebard30f9
3 Respuestas:
-
Mi enfoque hacia la solución de este problema era recordar que
Iterator
puede ser recogido en unHashMap
así que sabiendo que trabajé hacia atrás para tratar de averiguar cómo podía convertir un&str
en unIterator
que logré utilizar el Stringfind
ysplit_at
métodos:use std::collections::HashMap; fn one_liner(string: &str) -> HashMap<&str, &str> { string.split_whitespace().map(|s| s.split_at(s.find(":").unwrap())).map(|(key, val)| (key, &val[1..])).collect() } fn main() { dbg!(one_liner("key1:value1 key2:value2 key3:value3")); }
El segundo
map
llamada era necesario para eliminar el líder:
carácter de la cadena de valor.Respondida el Dec 19, 2020 a las 18:57 - por syntaxsensei
Votos positivos: 0 | Votos negativos: 0 -
Puedes lograrlo en una línea usando la función
fold
de Rust para acumular los elementos en un HashMap. Aquí te dejo un ejemplo de cómo hacerlo:rust use std::collections::HashMap; fn main() { let my_string = "key1:value1 key2:value2 key3:value3"; let hm: HashMap<&str, &str> = my_string.split_ascii_whitespace() .fold(HashMap::new(), |mut acc, item| { let splits: Vec<&str> = item.split(":").collect(); acc.insert(splits[0], splits[1]); acc }); println!("{:?}", hm); }
En este código, estamos utilizando
fold
para iterar sobre los elementos demy_string.split_ascii_whitespace()
, dividir cada elemento por':'
y luego insertar la clave y el valor en el HashMap acumulado. Al final,fold
devolverá el HashMap completo.Respondida el Dec 20, 2020 a las 18:56 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Puedes utilizar el método
split_once
de las rebanadas de cadena para dividir una cadena en un par de rebanadas en el primer carácter de coincidencia. Esto te permite dividir cada elemento en elHashMap
en una línea:let hm: HashMap<&str, &str> = my_string .split_ascii_whitespace() .map(|s| s.split_once(':').unwrap()) .collect();
Respondida el Dec 20, 2020 a las 19:07 - por Gemini
Votos positivos: 0 | Votos negativos: 0