Well, that doesn't really tell me the problem you're trying to solve. But I guess if you need that specific output, then your code looks about right to me. Why do you feel it is sub-optimal?
Now, for your particular regex, every single capture group is guaranteed to be present in a match, so there are a few case analyses that you can safely omit:
for (i, cg_name) in re.capture_names().enumerate() {
match cg_name {
None => {
println!("({},{})", i, &caps[i]);
}
Some(cap_name) => {
println!("({},{})", cap_name, &caps[cap_name]);
}
}
}
With that said, you were already using caps.name(cap_name).unwrap().as_str()
, which is equivalent to &caps[cap_name]
while simultaneously checking the return value of caps.get(i)
. Doing one and not the other doesn't really make sense. (Unless I guess you know that every named group must participate in a match while some unnamed groups don't participate in a match.) So, to handle it fully correctly for any regex, you would need to do:
for (i, cg_name) in re.capture_names().enumerate() {
match cg_name {
None => {
if let Some(m) = caps.get(i) {
println!("({},{})", i, m.as_str());
}
}
Some(cap_name) => {
if let Some(m) = caps.name(cap_name) {
println!("({},{})", cap_name, m.as_str());
}
}
}
}
Another approach:
let mut index_to_name: HashMap<usize, String> = HashMap::new();
for (i, name) in re.capture_names().enumerate() {
if let Some(name) = name {
index_to_name.insert(i, name.to_string());
}
}
for (i, group) in caps.iter().enumerate() {
let m = match group {
None => continue,
Some(m) => m,
};
if let Some(name) = index_to_name.get(&i) {
println!("({},{})", name, m.as_str());
} else {
println!("({},{})", i, m.as_str());
}
}
But that requires allocating a hash map, and it's not really that much simpler. Really depends on what you're doing...
Again, I don't see what is sub-optimal about any of this.