【问题标题】:How to check if for loop is on the last element of an iterator?如何检查 for 循环是否在迭代器的最后一个元素上?
【发布时间】:2021-08-24 13:52:59
【问题描述】:

我正在尝试找到一种方法来检查我是否在 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);
    }
}

有没有办法以更简洁的方式做到这一点,也许只使用原始迭代器?

【问题讨论】:

  • BTW 使用enumerate 在您需要索引时非常合适。没有理由避免它。
  • @DenysSéguret 这对我来说似乎是多余的,我必须将迭代器转换为向量,然后再次将其转换回迭代器以获取索引
  • 转换为 vec 是一个合法的问题,是的。在最后一个迭代器项目的一般情况下,您可以在下面找到 Masklinn 的答案,它优雅地缓冲下一个元素。在你的确切情况下,你有我的更简单,更有效。但在真正需要索引的一般情况下,请使用enumerate

标签: rust


【解决方案1】:

对于有限迭代器的一般情况,如果您想获取最后一项,您可以按照@Masklinn(请参阅他们的答案)的建议转换为Peekable,它将缓冲,因此它始终知道下一个元素。

在您的精确情况下,当您只想打印最后一个单词而不关心其他单词时,一个更便宜的解决方案,因为在字符上拆分实现了DoubleEndedIterator

所以很容易得到最后一个词,你不必收集整个拆分也不必枚举。它也很快,因为将从末尾搜索字符串并且不会复制任何内容。

所以你可以这样做

let last_word = sentence
    .split(' ').rev().next().unwrap(); // SAFETY: there's always at least one word

【讨论】:

  • 通过peekable 有一个完全通用的解决方案(当然,如果输入无限迭代器,结果可能会出乎意料)。
【解决方案2】:

将您的迭代器转换为Peekable

这需要将迭代脱糖为while let,但如果在迭代期间peek() 返回None,您就处于最后一次迭代:

let mut it = sentence.split(' ').peekable();
while let Some(word) = it.next()  {
    if it.peek().is_none() {
        println!("{}", word);
    }
}

Playground.

【讨论】:

    【解决方案3】:

    您可以利用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);
       }
    }
    

    这样,您不必处理循环体中的索引,您只需关注特定迭代中的给定元素是否是最后一个。

    【讨论】:

      猜你喜欢
      • 2016-11-20
      • 1970-01-01
      • 2016-02-12
      • 2011-08-30
      • 2017-08-02
      • 1970-01-01
      • 2010-10-24
      • 1970-01-01
      相关资源
      最近更新 更多