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

String equality in Rust: how does referencing and dereferencing work?

作为 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());
    }
}

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

解决方案一:

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

方案二:

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();

我希望有人能给我解释一下:

谢谢!

  1. Vec<String>.iter() returns 对引用 (&String) 的迭代器。
  2. .filter() 的闭包参数引用了迭代器的项。所以传递给闭包的类型是双引用 &&String.
  3. |&x| 告诉闭包期待一个引用,所以 x 现在是 &String.
  4. 类型

第一个方案:collectreturns一个String,其中&取参考。 x也是对字符串的引用,所以比较的是两个&String.

第二种解决方案:取消引用运算符 * 应用于 x,结果是 String。右侧很有趣:collectString 结果被取消引用。这会导致字符串切片,因为标准库中的 String implements Deref<Target=str>. Now the comparison is between String and str, which is works because it is implemented(请注意,a == b 等同于 a.eq(&b))。

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

the trait std::cmp::PartialEq<std::string::String> is not implemented for &&std::string::String

左边是对字符串 (&&String) 的双重引用,右边只是一个 String你需要让双方都一样 "reference level"。 所有这些工作:

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>());