Optimize 'windowed' and 'chunked' for char sequences, iterables and sequences

This commit is contained in:
Ilya Gorbunov
2017-05-04 23:08:57 +03:00
parent 18c7a01ab5
commit 3f23742298
8 changed files with 236 additions and 179 deletions
@@ -1790,7 +1790,7 @@ public fun <T : Any> List<T?>.requireNoNulls(): List<T> {
@SinceKotlin("1.2")
public fun <T> Iterable<T>.chunked(size: Int): List<List<T>> {
return chunked(size) { it.toList() }
return windowed(size, size)
}
@SinceKotlin("1.2")
@@ -1988,15 +1988,44 @@ public inline fun <T> Collection<T>.plusElement(element: T): List<T> {
@SinceKotlin("1.2")
public fun <T> Iterable<T>.windowed(size: Int, step: Int): List<List<T>> {
return windowed(size, step) { it.toList() }
checkWindowSizeStep(size, step)
if (this is RandomAccess && this is List) {
val thisSize = this.size
val result = ArrayList<List<T>>((thisSize + step - 1) / step)
var index = 0
while (index < thisSize) {
result.add(List(size.coerceAtMost(thisSize - index)) { this[it + index] })
index += step
}
return result
}
val result = ArrayList<List<T>>()
windowedIterator(iterator(), size, step, dropTrailing = false, reuseBuffer = false).forEach {
result.add(it)
}
return result
}
@SinceKotlin("1.2")
public fun <T, R> Iterable<T>.windowed(size: Int, step: Int, transform: (List<T>) -> R): List<R> {
if (this is List) {
return windowIndices(this.size, size, step, dropTrailing = false).asIterable().map { transform(subList(it.start, it.endInclusive + 1)) }
checkWindowSizeStep(size, step)
if (this is RandomAccess && this is List) {
val thisSize = this.size
val result = ArrayList<R>((thisSize + step - 1) / step)
val window = MovingSubList(this)
var index = 0
while (index < thisSize) {
window.move(index, (index + size).coerceAtMost(thisSize))
result.add(transform(window))
index += step
}
return result
}
return windowForwardOnlySequenceImpl(iterator(), size, step, dropTrailing = false).asIterable().map(transform)
val result = ArrayList<R>()
windowedIterator(iterator(), size, step, dropTrailing = false, reuseBuffer = true).forEach {
result.add(transform(it))
}
return result
}
/**
@@ -1311,7 +1311,7 @@ public fun <T : Any> Sequence<T?>.requireNoNulls(): Sequence<T> {
@SinceKotlin("1.2")
public fun <T> Sequence<T>.chunked(size: Int): Sequence<List<T>> {
return chunked(size) { it.toList() }
return windowed(size, size)
}
@SinceKotlin("1.2")
@@ -1497,13 +1497,12 @@ public inline fun <T> Sequence<T>.plusElement(element: T): Sequence<T> {
@SinceKotlin("1.2")
public fun <T> Sequence<T>.windowed(size: Int, step: Int): Sequence<List<T>> {
return windowed(size, step) { it.toList() }
return windowedSequence(size, step, dropTrailing = false, reuseBuffer = false)
}
@SinceKotlin("1.2")
public fun <T, R> Sequence<T>.windowed(size: Int, step: Int, transform: (List<T>) -> R): Sequence<R> {
require(size > 0 && step > 0) { "size $size and step $step both must be greater than zero" }
return Sequence { windowForwardOnlySequenceImpl(iterator(), size, step, dropTrailing = false).iterator() }.map(transform)
return windowedSequence(size, step, dropTrailing = false, reuseBuffer = true).map(transform)
}
/**
@@ -1104,7 +1104,7 @@ public inline fun CharSequence.sumByDouble(selector: (Char) -> Double): Double {
@SinceKotlin("1.2")
public fun CharSequence.chunked(size: Int): List<String> {
return chunked(size) { it.toString() }
return windowed(size, size)
}
@SinceKotlin("1.2")
@@ -1181,7 +1181,15 @@ public fun CharSequence.windowed(size: Int, step: Int): List<String> {
@SinceKotlin("1.2")
public fun <R> CharSequence.windowed(size: Int, step: Int, transform: (CharSequence) -> R): List<R> {
return windowIndices(this.length, size, step, dropTrailing = false).asIterable().map { transform(subSequence(it)) }
checkWindowSizeStep(size, step)
val thisSize = this.length
val result = ArrayList<R>((thisSize + step - 1) / step)
var index = 0
while (index < thisSize) {
result.add(transform(subSequence(index, (index + size).coerceAtMost(thisSize))))
index += step
}
return result
}
@SinceKotlin("1.2")
@@ -1191,7 +1199,8 @@ public fun CharSequence.windowedSequence(size: Int, step: Int): Sequence<String>
@SinceKotlin("1.2")
public fun <R> CharSequence.windowedSequence(size: Int, step: Int, transform: (CharSequence) -> R): Sequence<R> {
return windowIndices(this.length, size, step, dropTrailing = false).map { transform(subSequence(it)) }
checkWindowSizeStep(size, step)
return (indices step step).asSequence().map { index -> transform(subSequence(index, (index + size).coerceAtMost(length))) }
}
/**