2016-08-12 112 views
2

要遍历所有的指数,跟踪下一个/上述项目中,它可以如下完成。迭代循环包装索引的最佳方式是什么?

for index_prev in 0..n { 
    let index_next = (index_prev + 1) % n; 

    // some arbitrary code... 
    some_function(index_prev, index_next); 
} 

这可以由通过避免模,而是做更有效的:

提供了索引包装可以由一个偏移。

let mut index_prev = n - 1; 
for index_next in 0..n { 

    // some arbitrary code... 
    some_function(index_prev, index_next); 

    index_prev = index_next; 
} 

虽然这个工作,它有一些缺点:需要申报

  • index_prev需求可变的,当我们真正要循环不变的指数。
  • index_prev需要在外部作用域名称空间声明,而不是被限制在for循环。

虽然这些都不是可怕的他们使解决方案不理想。


是否有一个高性能的&便捷的方式在拉斯特做到这一点还是需要编写一个自定义的迭代器?

什么在鲁斯特做到这一点的最好方法是什么?

回答

3
fn main() { 
    let n = 10; 
    for (prev, next) in (0..n).zip(1..n+1) { 
     println!("{}, {}", prev, next % n); 
    } 
} 

为您提供:

0, 1 
1, 2 
.... 
9, 0 

或者,如果你真的不想要使用的模数,则:

for (prev, next) in (0..n).zip((0..n).cycle().skip(1)) { 

的工作,但可能会产生更多的代码。

另一种方法是包裹需要键入自己实现迭代或[x]吸气剂,其正确处理溢出。也就是说,总是从底层结构获得[x%n]

+0

第一个例子中的一面是你需要,只要你引用它使用'下一%N'。例如,偶然使用'vector [next]'会导致索引错误(除了每次使用模的可能开销以及需要额外的输入)。 – ideasman42

+0

@ ideasman42你知道,除非这是一些CPU重的热循环的中心,否则一个额外的模块不会被注意到,对吗?另一种选择是将你的缓冲区包装到一个实现更高索引的结构中,并且透明地进行环绕 - 它不会摆脱它,但是使它不可能被忽略。 – viraptor

+0

对,我主要关心的是'向量[下一页]'读作正确的代码,但不会工作,或者更糟 - 静静地读过去的预期范围。在实践中,'n'可能是'path.to.some.vector.len()',使得vector [下一个%path.to.some.vector.len()]繁琐写出来。 – ideasman42

相关问题