str 之类的迭代器

Lap*_*try 2 string rust

当我研究 Rust 时,我试图编写一个 Rust 函数来查看任何可迭代的字符串。

我最初的尝试是

fn example_1(iter: impl Iterator<Item=&str>);
fn example_2(iter: impl Iterator<Item=&String>);
// ...
Run Code Online (Sandbox Code Playgroud)

这需要针对不同情况的两个函数。

我也尝试将上面的案例合并为一个,我得到的是:

fn example_3<'a, T: 'a + ?Sized + Deref<str>>(iter: impl Iterator<Item=&'a T>);
Run Code Online (Sandbox Code Playgroud)

可以接受Iterator<Item=&String>Iterator<Item=&str>,但不能接受Iterator<String>(因为最后一个需要在函数体中再借用一次)。而且,它看起来比应有的要复杂得多。

我当然可以使用 custom 来实现这一点trait,也许涉及AsRef,但我认为我可能会错过一种更好、更清晰的方法。

Sil*_*olo 7

这是一个很好的用例std::borrow::BorrowBorrow适用于可以合理借用为外观相似但实际上不相同的类型的类型(String借用为&strPathBuf借用为&Path等)

fn example<'a, I, T>(iter: I)
where I : Iterator<Item=T>,
      T : Borrow<str> {
  for x in iter {
    let my_string: &str = x.borrow();
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这适用于String&str,但不适用于您在示例中建议的&String。如果你最终得到一个 的迭代器&String,那么你可能会质疑你是如何到达那里的(&String出于同样的原因,它是无用的&Vec<T>;客观上它比&str各方面都更糟糕)。但是如果由于某种原因你最终得到了 的迭代器&String,你可以&str使用

my_iter.map(|x| &**x));
Run Code Online (Sandbox Code Playgroud)

一个*摆脱了&,一个*取消引用Stringto str,然后&借用了str。恭喜!你现在是一名二星级程序员了。

或者,更简单(谢谢,user4815162342),

my_iter.map(|x| x.as_str())
Run Code Online (Sandbox Code Playgroud)


ape*_*lla 6

您可以使用两个泛型更轻松地完成此操作,一个表示字符串类型,另一个表示迭代器。虽然您可以使用 来做到这一点DerefAsRef但这里的特征会更好,因为AsRef给定类型可以有多种实现,而且它更通用一些。&str下面是一个可与、&StringString等一起使用的示例。

fn example<S: AsRef<str>, T: Iterator<Item=S>>(iter: T) {
    for string in iter {
        println!("String: {}", string.as_ref());
    }
}
Run Code Online (Sandbox Code Playgroud)