如何有效地将字符串中的键值对提取到HashMapwhen
key后面总是跟:然后是值value以 a 结尾,,后跟另一个key(有时是空格然后是key)value 可以包含 , :整个value包括任何keykeys不固定key名被称为对于这些键值对
key1:value1, key2:this is, some value2, key3:anothe:r val,ue,
Run Code Online (Sandbox Code Playgroud)
它应该产生这个HashMap:
"key1", "value1"
"key2", "this is, some value2"
"key3", "anothe:r val,ue"
Run Code Online (Sandbox Code Playgroud)
我已经尝试了以下代码,但仅将 a,作为分隔符是不好的,因为该值可以始终包含逗号。
"key1:value1, key2:this is, some value2, key3:anothe:r val,ue,"
.split(",")
.map(|kv| kv.splitn(2, ":").collect::<Vec<&str>>())
.filter(|vec| vec.len() == 2)
.map(|vec| (vec[0].trim().into(), vec[1].trim().into()))
.collect()
Run Code Online (Sandbox Code Playgroud)
我的想法是提供一个键列表: ["key1", "key2", "key3"]用作分隔符
更新:
使用@Lucretiel 回答我想出了:
fn key_value<'a>(keys: &[&str], mut command: &'a str) -> HashMap<&'a str, &'a str> {
let mut hashmap = HashMap::new();
loop {
if let Some(key) = key(&keys, &command) {
command = &command[key.len() + 1..];
let value = value(&keys, &command);
let trim: &[_] = &[',', ' '];
command = &command[value.len()..].trim_start_matches(trim);
hashmap.insert(key, value);
} else {
break;
}
}
hashmap
}
fn key<'a>(keys: &[&str], command: &'a str) -> Option<&'a str> {
let regex = format!("^({}):", keys.join("|"));
let regex = regex::Regex::new(®ex).expect("Invalid regex");
match regex.shortest_match(&command) {
Some(position) => Some(&command[..position - 1]),
None => None,
}
}
fn value<'a>(keys: &[&str], command: &'a str) -> &'a str {
let regex = format!(r#",\s*({}):"#, keys.join("|"));
let regex = regex::Regex::new(®ex).expect("Invalid regex");
match regex.find(&command) {
Some(position) => &command[..position.start()],
None => command,
}
}
Run Code Online (Sandbox Code Playgroud)
(游乐场)
解决这个问题的实际代码并不简单,但它是可以做到的。有很多棘手的边缘情况,具体取决于您想要考虑的错误情况(例如,您是否要求已知键列表中的每个键都存在于要解析的输入字符串中?您是否允许重复的键?等等.)。基本算法如下所示:
^{key}:. 这是当前的密钥。
,\s*{key}:一个最早的键,匹配。这是下一个关键。
传统语法无法做到这一点;正如所呈现的那样,它非常含糊。但是,如果围绕扫描每个后续键来构造解析(假设键永远不会作为值中的子字符串出现),则可以成功解析此类输入。
所描述的算法以二次时间运行,但假设如果您创建一个复合正则表达式来同时搜索每个键,它应该可以简化为线性时间:
,\s*(key1|key2|key3|...):
| 归档时间: |
|
| 查看次数: |
443 次 |
| 最近记录: |