【问题标题】:Regex capture iterator method moves iterator正则表达式捕获迭代器方法移动迭代器
【发布时间】:2015-08-14 16:02:14
【问题描述】:

我正在使用此正则表达式处理格式为“1s:1d”、“100:5000”等的简单字符串:

let retention_matcher = regex::Regex::new({r"^(\d+)([smhdy])?:(\d+)([smhdy])?$"}).unwrap();

我知道这个正则表达式应该只匹配一次,所以我想运行正则表达式进行捕获并检查捕获的数量。

    let iter = retention_matcher.captures_iter(ts);
    let count = iter.count();
    println!("iter.count(): {}", count);

    let _ : Vec<Option<(u64,u64)>> = iter.map(|regex_match| {
        let retval = retention_spec_to_pair(regex_match);
        println!("precision_opt: {:?}", retval);
        retval
    }).collect();

问题是count() 方法移动了iter,我不能再使用它了。

src/bin/whisper.rs:147:42: 147:46 error: use of moved value: `iter`
src/bin/whisper.rs:147         let _ : Vec<Option<(u64,u64)>> = iter.map(|regex_match| {
                                                                ^~~~
src/bin/whisper.rs:144:21: 144:25 note: `iter` moved here because it has type `regex::re::FindCaptures<'_, '_>`, which is non-copyable
src/bin/whisper.rs:144         let count = iter.count();

这对我来说没有意义。 count 方法是否应该只返回一个可复制的usize 值而不移动iter?我该如何解决这个问题?

【问题讨论】:

  • 如果您只需要一组捕获,请使用retention_matcher.captures(ts)。它的合同似乎与您的用例完全匹配。 (实际上,您的正则表达式是完全锚定的,因此它只能为特定字符串生成一个匹配项。)无需使用迭代器。 :-)

标签: regex iterator rust borrow-checker


【解决方案1】:

我怀疑您认为iter 是一个抽象的捕获序列。将其视为代表抽象捕获序列中的 位置 更为准确。任何迭代器都知道要做的基本事情是前进到序列中的下一项;即可以提前位置,获取序列中的下一个元素。

count 移动iter 因为为了计算序列中有多少元素,它必须生成整个序列。这必然通过逐步遍历整个序列来修改迭代器。它移动是因为在调用count 之后,迭代器真的不再有用了。根据定义,它必须超过序列的末尾!

遗憾的是,有问题的迭代器类型 (FindCaptures) 看起来不像是 Clone,因此您不能只复制它。

解决方案是将您的代码重构为调用count。如果您想获取第一个元素并确保没有更多元素,最简单的模式是:

let mut iter = ...;
if let Some(regex_match) = iter.next() {
    // Ensure that there is no next element.
    assert_eq!(iter.next(), None);

    // process regex_match ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 2013-05-24
    • 2013-07-30
    • 2019-09-27
    相关资源
    最近更新 更多