如何重用 SplitWhitespace 迭代器?

Riv*_*Tam 3 rust

我有一段代码,应该检查两个句子是否“太相似”,正如代码中最清楚的启发式所定义的那样。

fn too_similar(thing1: &String, thing2: &String) -> bool {
    let split1 = thing1.split_whitespace();
    let split2 = thing2.split_whitespace();

    let mut matches = 0;
    for s1 in split1 {
        for s2 in split2 {
            if s1.eq(s2) {
                matches = matches + 1;
                break;
            }
        }
    }

    let longer_length =
        if thing1.len() > thing2.len() {
            thing1.len()
        } else {
            thing2.len()
        };

    matches > longer_length / 2
}
Run Code Online (Sandbox Code Playgroud)

但是,我收到以下编译错误:

fn too_similar(thing1: &String, thing2: &String) -> bool {
    let split1 = thing1.split_whitespace();
    let split2 = thing2.split_whitespace();

    let mut matches = 0;
    for s1 in split1 {
        for s2 in split2 {
            if s1.eq(s2) {
                matches = matches + 1;
                break;
            }
        }
    }

    let longer_length =
        if thing1.len() > thing2.len() {
            thing1.len()
        } else {
            thing2.len()
        };

    matches > longer_length / 2
}
Run Code Online (Sandbox Code Playgroud)

我不确定为什么split2要移动,但是编写这个函数的 Rust 方式是什么?

Dog*_*ert 5

split2正在被移动,因为迭代 withfor会消耗迭代器,并且由于该类型没有实现Copy,Rust 不会隐式复制它。

您可以通过在第一个迭代器中创建一个新的迭代器来解决此问题for

let split1 = thing1.split_whitespace();

let mut matches = 0;
for s1 in split1 {
    for s2 in thing2.split_whitespace() {
        if s1.eq(s2) {
            matches = matches + 1;
            break;
        }
    }
}
...
Run Code Online (Sandbox Code Playgroud)

matches您还可以使用特征中可用的一些高阶函数重写计数循环Iterator

let matches = thing1.split_whitespace()
    .flat_map(|c1| thing2.split_whitespace().filter(move |&c2| c1 == c2))
    .count();
Run Code Online (Sandbox Code Playgroud)

longer_length也可以写成:

let longer_length = std::cmp::max(thing1.len(), thing2.len());
Run Code Online (Sandbox Code Playgroud)

  • https://github.com/rust-lang/rust/issues/18045 解释了为什么 `SplitWhitespace` 没有实现 `Copy`。此外,这不会比 `SplitWhitespace` 实现 `Copy` 慢,因为迭代器是惰性的,并且与迭代拆分所需的时间相比,创建 `SplitWhitespace` 结构的开销可以忽略不计。 (2认同)