在 Rust 中将正则表达式捕获转换为 HashMap?

And*_*ers 3 regex hashmap regex-group rust

我有一个Regex名称未知的命名组。我想将一个字符串与该正则表达式相匹配,并获得一个HashMap<&str, &str>以组名作为键和捕获的字符串作为值的字符串。

我怎样才能做到这一点?我是否必须使用regex.captures(str).iter()然后以某种方式映射和过滤并收集到地图中?或者有什么捷径?

rod*_*igo 6

这很棘手,因为正则表达式可以有多个匹配项,并且每个捕获可以在单个全局匹配项中多次匹配。

也许是这样的(游乐场)

fn main() {
    let re = Regex::new(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})").unwrap();
    let text = "2012-03-14";
    let caps = re.captures(text).unwrap();
    let dict: HashMap<&str, &str> = re
        .capture_names()
        .flatten()
        .filter_map(|n| Some((n, caps.name(n)?.as_str())))
        .collect();
    println!("{:#?}", dict);
}
Run Code Online (Sandbox Code Playgroud)

输出:

fn main() {
    let re = Regex::new(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})").unwrap();
    let text = "2012-03-14";
    let caps = re.captures(text).unwrap();
    let dict: HashMap<&str, &str> = re
        .capture_names()
        .flatten()
        .filter_map(|n| Some((n, caps.name(n)?.as_str())))
        .collect();
    println!("{:#?}", dict);
}
Run Code Online (Sandbox Code Playgroud)

一旦您意识到捕获名称不能从Match自身获得,而是从父获得,代码就很简单了Regex。您必须执行以下操作:

  1. 调用capture_names(),这将是Option<&str>.
  2. flatten()可迭代,这将消除None解开&str值。
  3. filter_map()将捕获名称转换为类型为 的元组(名称、值)列表(&str, &str)。的filter需要,以除去不存在(由于@Anders)捕获。
  4. collect()!这只是有效,因为HashMap<K, V>实现了 trait FromIterator<(K, V)>,所以(&str, &str)collects的迭代器变成了HasMap<&str, &str>.

  • 如果缺少命名组,则会出现恐慌。它可以通过使用 `filter_map(|n| Some((n, captures.name(n)?.as_str())))` 而不是 `map` 来修复。 (2认同)
  • @Anders:哦,你说得对。我会按照你的建议修复它。尽管更惯用的解决方案是创建一个 `HasMap&lt;&amp;str, Option&lt;&amp;str&gt;&gt;`,而是使用 `map(|n| (n, caps.name(n).map(|m| m.as_str() )))` (2认同)