问题描述
我试图找到一种方法来检查我是否在 for 循环中的迭代器的最后一个元素上,而不使用 .clone();目前我正在这样做:
let sentence = "The quick brown fox.";
let words = sentence.split(' ');
let last = words.clone().last().unwrap();
for word in words {
if word == last {
print!("{}",word);
}
}
我也尝试在迭代器上使用 .collect() ,但这需要我使用 .iter().enumerate() 来检查最后一个索引,这对我来说似乎不必要地复杂:
let sentence = "The quick brown fox.";
let words: Vec<&str> = sentence.split(' ').collect();
for (i,word) in words.iter().enumerate() {
if i == words.len() - 1 {
print!("{}",word);
}
}
有没有办法以更简洁的方式做到这一点,也许只是使用原始迭代器?
解决方法
将您的迭代器转换为 Peekable
。
这将需要将迭代脱糖为 while let
,但如果在迭代期间 peek()
返回 None
,则您处于最后一次迭代:
let mut it = sentence.split(' ').peekable();
while let Some(word) = it.next() {
if it.peek().is_none() {
println!("{}",word);
}
}
,
对于有限迭代器的一般情况,如果你想获得最后一项,你可以按照@Masklinn(见他们的答案)的建议,转换为一个 Peekable
,它会缓冲所以它总是知道下一个元素。
在您的确切情况下,当您只想打印最后一个单词而不关心其他单词时, 有一个便宜得多的解决方案,因为拆分字符实现了 {{1} }.
所以很容易得到最后一个词,您不必收集整个拆分或枚举。它也很快,因为将从末尾开始搜索字符串并且不会复制任何内容。
所以你可以这样做
DoubleEndedIterator
,
您可以利用 Iterator::map()
迭代器适配器来实现更方便的使用:
let sentence = "The quick brown fox.";
let words: Vec<&str> = sentence.split(' ').collect();
for (word,is_last_element) in words.iter().enumerate()
.map(|(i,w)| (w,i == words.len() - 1))
{
if is_last_element {
println!("{}",word);
}
}
这样,您不必处理循环体中的索引,而只需关注特定迭代中的给定元素是否是最后一个。