Rust中的字符串相等性:引用和解除引用的工作原理是什么?

时间:2018-05-02 11:35:10

标签: string rust dereference 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());
    }
}

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

解决方案1:

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

解决方案2:

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

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

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

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

我期望能够做到的事情:

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

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

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

谢谢!

1 个答案:

答案 0 :(得分:8)

  1. Vec<String>.iter()返回引用(&String)上的迭代器。
  2. .filter()的闭包参数引用了迭代器的项目。因此传递给闭包的类型是双引用&&String
  3. |&x|告诉闭包期望引用,因此x现在属于&String类型。
  4. 第一个解决方案:collect返回String,其中&获取引用。 x也是对字符串的引用,因此比较在两个&String之间。

    第二个解决方案:取消引用运算符*应用于x,结果为String。右侧很有趣:String的{​​{1}}结果被解除引用。这导致字符串切片,因为String implements Deref<Target=str>。现在,比较是collectString之间的比较,因为标准库中的implemented是有效的(请注意str等同于a == b)。

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

      

    a.eq(&b)

    未实现特征std::cmp::PartialEq<std::string::String>

    左侧是字符串(&&std::string::String)的双重引用,右侧是&&String你需要让双方达到相同的水平&#34;参考水平&#34;。所有这些工作:

    String