在 Rust 中将正则表达式捕获转换为 HashMap?
Convert regex Captures into HashMap in Rust?
我有一个 Regex
,其中包含数量未知且名称未知的命名组。我想将一个字符串与该正则表达式匹配,并得到一个 HashMap<&str, &str>
,其中组名作为键,捕获的字符串作为值。
我该怎么做?我是否必须使用 regex.captures(str).iter()
然后以某种方式映射和过滤并收集到地图中?或者有什么捷径?
这很棘手,因为正则表达式可以有多个匹配,并且每个捕获可以在单个全局匹配中匹配多次。
也许是这样的(playground):
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);
}
输出:
{
"y": "2012",
"d": "14",
"m": "03"
}
一旦您意识到捕获名称无法从 Match
本身获得,而是从父级 Regex
获得,代码就很简单了。您必须执行以下操作:
- 调用
capture_names()
,这将是 Option<&str>
的可迭代对象。
flatten()
可迭代对象,它将删除 None
和 unwrap &str
值。
filter_map()
将名称捕获到类型 (&str, &str)
的元组列表 (名称,值) 中。 filter
需要删除不存在的捕获(感谢@Anders)。
collect()
!这之所以有效,是因为 HashMap<K, V>
实现了特征 FromIterator<(K, V)>
,因此 (&str, &str)
的迭代器收集到 HasMap<&str, &str>
.
如果您有多个捕获,您可以将它们收集到这样的列表中:
let all: Vec<HashMap<&str, &str>> = re
.captures_iter("2012-01-12 , 2013-07-11 , 2014-09-14")
.map(|caps| {
re.capture_names()
.map(|o| o.and_then(|n| Some((n, caps.name(n)?.as_str()))))
.flatten()
.collect()
})
.collect();
println!("{:#?}", all);
我有一个 Regex
,其中包含数量未知且名称未知的命名组。我想将一个字符串与该正则表达式匹配,并得到一个 HashMap<&str, &str>
,其中组名作为键,捕获的字符串作为值。
我该怎么做?我是否必须使用 regex.captures(str).iter()
然后以某种方式映射和过滤并收集到地图中?或者有什么捷径?
这很棘手,因为正则表达式可以有多个匹配,并且每个捕获可以在单个全局匹配中匹配多次。
也许是这样的(playground):
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);
}
输出:
{
"y": "2012",
"d": "14",
"m": "03"
}
一旦您意识到捕获名称无法从 Match
本身获得,而是从父级 Regex
获得,代码就很简单了。您必须执行以下操作:
- 调用
capture_names()
,这将是Option<&str>
的可迭代对象。 flatten()
可迭代对象,它将删除None
和 unwrap&str
值。filter_map()
将名称捕获到类型(&str, &str)
的元组列表 (名称,值) 中。filter
需要删除不存在的捕获(感谢@Anders)。collect()
!这之所以有效,是因为HashMap<K, V>
实现了特征FromIterator<(K, V)>
,因此(&str, &str)
的迭代器收集到HasMap<&str, &str>
.
如果您有多个捕获,您可以将它们收集到这样的列表中:
let all: Vec<HashMap<&str, &str>> = re
.captures_iter("2012-01-12 , 2013-07-11 , 2014-09-14")
.map(|caps| {
re.capture_names()
.map(|o| o.and_then(|n| Some((n, caps.name(n)?.as_str()))))
.flatten()
.collect()
})
.collect();
println!("{:#?}", all);