Rust中的字符串相等性:引用和解除引用如何工作?

pie*_*bot 6 string dereference rust borrowing

作为Rust新手,我正在解决Project Euler问题,以帮助我了解语言.问题4涉及回文,我找到了两个用于创建回文矢量的解决方案,但我不确定它们中的任何一个是如何工作的.

我正在使用一个字符串向量products,它的计算如下:

let mut products = Vec::new();
for i in 100..500 {
    for j in 500..1000 {
        products.push((i * j).to_string());
    }
}
Run Code Online (Sandbox Code Playgroud)

为了将这些产品过滤到只有回文的产品,我有以下两种解决方案:

解决方案1:

let palindromes: Vec<_> = products
    .iter()
    .filter(|&x| x == &x.chars().rev().collect::<String>())
    .collect();
Run Code Online (Sandbox Code Playgroud)

解决方案2:

let palindromes: Vec<_> = products
    .iter()
    .filter(|&x| *x == *x.chars().rev().collect::<String>())
    .collect();
Run Code Online (Sandbox Code Playgroud)

他们都产生了正确的结果,但我不明白为什么!

在解决方案1中,我们将字符串的引用与我们刚刚创建的字符串的引用进行比较?

在解决方案2中,我们取消引用对字符串的引用并将其与解除引用的新字符串进行比较?

我期望能做什么:

let palindromes: Vec<_> = products
    .iter()
    .filter(|x| x == x.chars().rev().collect::<String>())
    .collect();
Run Code Online (Sandbox Code Playgroud)

我希望有人能够向我解释:

  • 我的两个解决方案之间有什么区别,为什么它们都有效?
  • 为什么我不能x在我的过滤器功能中使用而不引用或取消引用它?

谢谢!

kaz*_*ase 8

  1. Vec<String>.iter()返回引用(&String)上的迭代器.
  2. closure参数.filter()接受迭代器项的引用.因此传递给闭包的类型是双引用&&String.
  3. |&x|告诉闭包期望引用,所以x现在是类型&String.

第一个解决方案:collect返回a String,其中&包含引用.x也是对字符串的引用,因此比较是在两者之间&String.

第二种解决方案:*应用dereference运算符x,结果为a String.右边很有意思:String结果collect被解除引用.这导致字符串切片,因为String实现Deref<Target=str>.现在比较是在String和之间str,这是有效的,因为它是在标准库中实现的(注意a == b相当于a.eq(&b)).

第三种解决方案:编译器解释了为什么它不起作用.

特质std::cmp::PartialEq<std::string::String>没有实现&&std::string::String

左边是对string(&&String)的双引用,右边是a String.你需要让双方都达到相同的"参考水平".所有这些工作:

x.iter().filter(|x| x == &&x.chars().rev().collect::<String>());
x.iter().filter(|x| *x == &x.chars().rev().collect::<String>());
x.iter().filter(|x| **x == x.chars().rev().collect::<String>());
Run Code Online (Sandbox Code Playgroud)

  • @piercebot逐个案例.如果你看一下[`filter`]的定义(https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.filter)你可以看到它需要一个关闭`&Iter项目:: Item`.相反,例如`filter_map`接受的闭包需要`Iter :: Item`,它不是引用. (4认同)