2016-08-12 260 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

相關問題