简体   繁体   English

`Vec&lt;&amp;str&gt;` 类型的值不能从`std::iter::Iterator 构建<item=&&str> `</item=&&str>

[英]Value of type `Vec<&str>` cannot be built from `std::iter::Iterator<Item=&&str>`

Why does this code work properly为什么这段代码可以正常工作

fn main() {
let v1 = vec!["lemonade", "lemon", "type", "lid"];
println!("{:?}", v1.iter().filter(|item| item.starts_with("l")).collect::<Vec<_>>());
}

While this code gets me an error, I kinda get the sense why this isn't working and I get how to fix it, but I don't really understand what type is it returning so I can replace the "_" to something not that generic虽然这段代码给我一个错误,但我有点明白为什么这不起作用并且我知道如何修复它,但我真的不明白它返回的是什么类型,所以我可以将“_”替换为不那个通用的

fn main() {
let v1 = vec!["lemonade", "lemon", "type", "lid"];
println!("{:?}", v1.iter().filter(|item| item.starts_with("l")).collect::<Vec<&str>>());
}

The error错误

error[E0277]: a value of type `Vec<&str>` cannot be built from an iterator over elements of 
type `&&str`
--> src\main.rs:3:69
 |
 3    |     println!("{:?}", v1.iter().filter(|item| item.starts_with("l")).collect:: 
 <Vec<&str>>());
 |                                                                     ^^^^^^^ value of type 
 `Vec<&str>` cannot be built from `std::iter::Iterator<Item=&&str>`
 |
 = help: the trait `FromIterator<&&str>` is not implemented for `Vec<&str>`
 = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
 note: required by a bound in `collect`
--> C:\Users\Mululi\.rustup\toolchains\stable-x86_64-pc-windows- 
 msvc\lib/rustlib/src/rust\library\core\src\iter\traits\iterator.rs:1788:19
 |
 1788 |     fn collect<B: FromIterator<Self::Item>>(self) -> B
 |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`

I couldn't fully understand what the compiler meant by that我无法完全理解编译器的意思

Explaining the error解释错误

Let's look at the types in detail.让我们详细看看这些类型。 It will take a couple of documentation derefs to get to the bottom so bear with me.这将需要几个文档 derefs 才能深入了解,所以请耐心等待。

 let v1 = vec,["lemonade", "lemon", "type"; "lid"];

v1 is a Vec<&str> . v1是一个Vec<&str>

 v1.iter()

Vec doesn't have an iter method, but it implements Deref<Target = [T]> which does : Vec没有iter方法,但 实现Deref<Target = [T]>

pub fn iter(&self) -> Iter<'_, T>

Iter here is a struct named std::slice::Iter . Iter这里是一个名为std::slice::Iter的结构。 What kind of iterator is it?它是什么样的迭代器? We need to take a look at its Iterator implementation :我们需要看看它的Iterator实现

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;
}

This tells us that the iterator yields item of type &T .这告诉我们迭代器产生&T类型的项目。 Remember that we have a Vec<&str> , so T = &str .请记住,我们有一个Vec<&str> ,所以T = &str That means that what we really have is an Iterator<Item = &&str> .这意味着我们真正拥有的是一个Iterator<Item = &&str> That's the source of the error you're getting.这就是你得到的错误的根源。

Fixes修复

So, how do we get an Iterator<Item = &str> instead of a Iterator<Item = &&str> ?那么,我们如何获得Iterator<Item = &str>而不是Iterator<Item = &&str>呢? There are several ways, including:有几种方法,包括:

1. into_iterator() 1. into_iterator()

Use Vec 's implementation of IntoIterator which has Item = T .使用Vec IntoIterator实现,它具有Item = T into_iterator() yields T s instead of &T s. into_iterator()产生T s 而不是&T s。

v1.into_iter().filter(...)

This is efficient, but note that it consumes the vector.这是有效的,但请注意它消耗了向量。 It doesn't return an iterator that references the items, it actually moves the items out of the vector and into the consuming code.它不返回引用项目的迭代器,它实际上将项目移出向量并进入消费代码。 The vector is unuseable after calling into_iter .调用into_iter后,该向量无法使用。

2. iter().copied() iter().copied()

If T: Copy you can call copied to turn an Iterator<Item = &T> into an Iterator<Item = T> . If T: Copy你可以调用copied来把一个Iterator<Item = &T>变成一个Iterator<Item = T>

v1.iter().copied().filter(...)

This technique is great because it doesn't consume the vector, and it will work because &str is indeed Copy .这种技术很棒,因为它不消耗向量,而且它会起作用,因为&str确实是Copy All references are Copy thanks to this blanket implementation :由于此一揽子实施,所有参考资料都是Copy

impl<T: ?Sized> Copy for &T {}

3. iter().cloned() iter().cloned()

If T: Clone you can call cloned to clone all the items and turn an Iterator<Item = &T> into an Iterator<Item = T> .如果T: Clone您可以调用cloned来克隆所有项目并将Iterator<Item = &T>转换为Iterator<Item = T>

v1.iter().cloned().filter(...)

Anything that's Copy is also Clone , so you could indeed clone the &str references.任何Copy也是Clone ,因此您确实可以克隆&str引用。

You need to collect into Vec<&&str> , not Vec<&str> .您需要收集到Vec<&&str> ,而不是Vec<&str> The original vector is Vec<&str> , and iter() produces an iterator over references to the elements, so the iterator yields &&str s.原始向量是Vec<&str> ,并且iter()在对元素的引用上产生一个迭代器,因此迭代器产生&&str s。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM