2017-02-23 79 views
2

我需要向後迭代數組的一部分。我想這樣做,「功能性」,因爲它是更容易理解,就像Kotlin lazy slice array

for (b in buf.sliceArray(0 until bufLimit).reversedArray()) {} 

但兩者sliceArrayreversedArray並不懶惰。有沒有懶惰的版本,或者我應該回落到

for (bIdx in bufLimit - 1 downTo 0) { 
    val b = buf[bIdx] 
} 

這是更令人困惑和詳細?

+0

這個是什麼? 'buf.take(bufLimit).reversed()。forEach {...}' – marstran

+0

@marstran'ByteArray.take'也不是懶惰的,它會創建一個'ArrayList' –

回答

1

如果你使用一個列表,而不是一個數組,那麼你可以扭轉它,然後轉換爲Sequence:與

val buf: List = listOf(1, 2, 3, 4, 5) 
val bufLimit = 3 

for (b in buf.asReversed().asSequence().drop(buf.size - bufLimit)) { 
    println(b) 
} 

功能as前綴只包裝對象而不復制,所以上面的代碼不會複製buf內容。

請注意,與Array相比,如果您使用ArrayList,則不應該失去任何性能。

但是這種解決方案並不涉及幾個迭代器,所以它一定程度上比你在問題中所建議的指數代碼效率較低:

for (bIdx in bufLimit - 1 downTo 0) { 
    val b = buf[bIdx] 
} 
1

我建議創建一個擴展函數來處理您的特定用例。例如:

/** 
* Performs the given [action] on each element at the specified [indices]. 
*/ 
inline fun ByteArray.forEachAt(indices: Iterable<Int>, action: (Byte) -> Unit): Unit { 
    indices.forEach { index -> action(this[index]) } 
} 

用法:

buf.forEachAt((0 until bufLimit).reversed)) {} 
// or 
buf.forEachAt(bufLimit - 1 downTo 0) {}