Rust 为什么可以';我不能用`&;迭代器<;项目=&;字符串>;`作为迭代器?
我有一个函数,它应该查找并返回给定Rust 为什么可以';我不能用`&;迭代器<;项目=&;字符串>;`作为迭代器?,rust,Rust,我有一个函数,它应该查找并返回给定迭代器的字符串的最长长度: fn max_width(strings: &Iterator<Item = &String>) -> usize { let mut max_width = 0; for string in strings { if string.len() > max_width { max_width = string.len();
迭代器的字符串的最长长度:
fn max_width(strings: &Iterator<Item = &String>) -> usize {
let mut max_width = 0;
for string in strings {
if string.len() > max_width {
max_width = string.len();
}
}
return max_width;
}
fn max_width<'a>(strings: impl Iterator<Item = &'a String>) -> usize
fn最大宽度(字符串:&迭代器)->usize{
设mut max_width=0;
对于字符串中的字符串{
if string.len()>最大宽度{
max_width=string.len();
}
}
返回最大宽度;
}
但是,编译器给了我以下错误:
error[E0277]:未满足特性绑定的'&std::iter::Iterator:std::iter::Iterator'
-->src/main.rs:3:19
|
3 |对于字符串中的字符串{
|^^^`&std::iter::Iterator`不是迭代器;可以尝试调用`.iter()`或类似的方法
|
=帮助:`&std::iter::Iterator`未实现特性'std::iter::Iterator'`
=注意:`std::iter::IntoIterator::into iter::所需`
我是个新手,对此感到非常困惑,因为我认为我是在显式地传递一个迭代器。调用strings.iter()
告诉我它没有实现,调用strings.into\u iter()
会让我陷入一个可变的兔子洞,我当然不想改变传递的参数
如何迭代字符串?如果您不特别需要迭代任何给定迭代器的通用性,编写函数的一种更简单的方法是让您的max_width
函数采用&[&str]
(一段字符串片段)相反,您可以在for
循环中使用切片,因为Rust知道如何将其转换为迭代器(它实现了IntoIterator
特性):
您的代码失败,因为它与&Iterator
不同。如果您将迭代器
传递给函数,则可以修复此问题,但由于迭代器
是一种特性,因此无法确定大小(您不知道传递的是什么迭代器
)。解决方案是传递实现迭代器的任何内容:
fn max_width(strings: &Iterator<Item = &String>) -> usize {
let mut max_width = 0;
for string in strings {
if string.len() > max_width {
max_width = string.len();
}
}
return max_width;
}
fn max_width<'a>(strings: impl Iterator<Item = &'a String>) -> usize
fn最大宽度)->使用
对于更有经验的用户:
最通用的方法可能是:
fn max_width<T: AsRef<str>>(strings: impl IntoIterator<Item = T>) -> usize {
let mut max_width = 0;
for string in strings {
let string = string.as_ref();
if string.len() > max_width {
max_width = string.len();
}
}
max_width
}
fn最大宽度(字符串:impl IntoIterator)->usize{
设mut max_width=0;
对于字符串中的字符串{
设string=string.as_ref();
if string.len()>最大宽度{
max_width=string.len();
}
}
最大宽度
}
但是,您也可以使用
fn max_width<T: AsRef<str>>(strings: impl IntoIterator<Item = T>) -> usize {
strings
.into_iter()
.map(|s| s.as_ref().len())
.max()
.unwrap_or(0)
}
fn最大宽度(字符串:impl IntoIterator)->usize{
串
.into_iter()
.map(| s | s.as_ref().len())
.max()
.展开或(0)
}
其他答案向您展示了如何接受迭代器,但掩盖了对实际问题的回答:
为什么我不能使用&Iterator
作为迭代器
有趣的是,你自己也阻止了它:
我当然不想改变已通过的论点
迭代器通过改变它们的目标来工作——这就是迭代器如何改变以为每个调用返回一个新值
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
// ^^^
}
pub特征迭代器{
类型项目;
fn next(&mut self)->选项;
// ^^^
}
通过接受一个不可变的trait对象,迭代器不可能更新自身,因此实际上不可能进行迭代
要使代码编译,您所能做的最简单的事情就是接受可变引用:
fn max_width(strings: &mut dyn Iterator<Item = &String>) -> usize
fn最大宽度(字符串:&mut-dyn迭代器)->usize
但是,我可能会将函数编写为:
fn max_width<I>(strings: I) -> usize
where
I: IntoIterator,
I::Item: AsRef<str>,
{
strings
.into_iter()
.map(|s| s.as_ref().len())
.max()
.unwrap_or(0)
}
fn最大宽度(字符串:I)->使用
哪里
I:迭代器,
I::项目:AsRef,
{
串
.into_iter()
.map(| s | s.as_ref().len())
.max()
.展开或(0)
}
不要使用显式的返回
使用迭代器组合符,如和
用于提供默认值
用于接受可以生成迭代器的任何内容
在函数末尾省略return
是惯用的方法。只需写max\u width
(不带分号)。谢谢,我会更新。Do&String
的deref也是&str
的,你不会通过吗?我想也许OP是Rust的新手,只是想迭代一堆字符串和一个Vec似乎是一种简单的方法。不过,通用解决方案很有趣。很抱歉,我应该添加我的用例!我正在解包fIELD从一个结构的向量(<代码> Max Sub(Cudiop.ItAudie).map(x x&x.NoX)),所以我已经有了一个迭代器,因此函数使用了它而不是vector。@ PJF如果你可以考虑用它来替换它:<代码> Cudio.Type()(map(x x.No.L..)).Max()。unRePAPIOR(0)
您也可以将您的用例添加到问题中:)这是可行的,但我很难理解语义。我知道,Iterator
是一种特性(因此可以是实现该特性的任何东西),但在此上下文中,我对impl
关键字感到困惑。我们以前没有过它,但它怎么会有已知的大小?我建议阅读。基本上,它与fn max_width(strings:t)相同->usize
。哦!所以Iterator
是特性本身,而impl Iterator
是实现该特性的东西。非常感谢!!谢谢@Tom。我认为这与旧链接相匹配。我更喜欢这个答案,因为它还提供了一个接近OP最初意图的解决方案,使用动态多态性。