windowed function: add default parameters, drop or keep partial windows, KEEP-11

Make step default to 1.
Add partialWindows boolean parameter defaulting to false to control
whether to keep partial windows in the end.
This commit is contained in:
Ilya Gorbunov
2017-07-27 00:57:58 +03:00
parent c04b0072af
commit 559255f38e
17 changed files with 336 additions and 142 deletions
@@ -1029,12 +1029,33 @@ public expect inline fun <T> Collection<T>.plusElement(element: T): List<T>
*
* Both [size] and [step] must be positive and can be greater than the number of elements in this collection.
* @param size the number of elements to take in each window
* @param step the number of elements to move the window forward by on an each step
* @param step the number of elements to move the window forward by on an each step, by default 1
* @param partialWindows controls whether or not to keep partial windows in the end if any,
* by default `false` which means partial windows won't be preserved
*
* @sample samples.collections.Sequences.Transformations.takeWindows
*/
@SinceKotlin("1.2")
public expect fun <T> Iterable<T>.windowed(size: Int, step: Int): List<List<T>>
public fun <T> Iterable<T>.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false): List<List<T>> {
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) {
val windowSize = size.coerceAtMost(thisSize - index)
if (windowSize < size && !partialWindows) break
result.add(List(windowSize) { this[it + index] })
index += step
}
return result
}
val result = ArrayList<List<T>>()
windowedIterator(iterator(), size, step, partialWindows, reuseBuffer = false).forEach {
result.add(it)
}
return result
}
/**
* Returns a list of results of applying the given [transform] function to
@@ -1047,12 +1068,34 @@ public expect fun <T> Iterable<T>.windowed(size: Int, step: Int): List<List<T>>
*
* Both [size] and [step] must be positive and can be greater than the number of elements in this collection.
* @param size the number of elements to take in each window
* @param step the number of elements to move the window forward by on an each step
* @param step the number of elements to move the window forward by on an each step, by default 1
* @param partialWindows controls whether or not to keep partial windows in the end if any,
* by default `false` which means partial windows won't be preserved
*
* @sample samples.collections.Sequences.Transformations.averageWindows
*/
@SinceKotlin("1.2")
public expect fun <T, R> Iterable<T>.windowed(size: Int, step: Int, transform: (List<T>) -> R): List<R>
public fun <T, R> Iterable<T>.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (List<T>) -> R): List<R> {
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))
if (!partialWindows && window.size < size) break
result.add(transform(window))
index += step
}
return result
}
val result = ArrayList<R>()
windowedIterator(iterator(), size, step, partialWindows, reuseBuffer = true).forEach {
result.add(transform(it))
}
return result
}
/**
* Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
@@ -952,12 +952,16 @@ public expect inline fun <T> Sequence<T>.plusElement(element: T): Sequence<T>
*
* Both [size] and [step] must be positive and can be greater than the number of elements in this sequence.
* @param size the number of elements to take in each window
* @param step the number of elements to move the window forward by on an each step
* @param step the number of elements to move the window forward by on an each step, by default 1
* @param partialWindows controls whether or not to keep partial windows in the end if any,
* by default `false` which means partial windows won't be preserved
*
* @sample samples.collections.Sequences.Transformations.takeWindows
*/
@SinceKotlin("1.2")
public expect fun <T> Sequence<T>.windowed(size: Int, step: Int): Sequence<List<T>>
public fun <T> Sequence<T>.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false): Sequence<List<T>> {
return windowedSequence(size, step, partialWindows, reuseBuffer = false)
}
/**
* Returns a sequence of results of applying the given [transform] function to
@@ -970,12 +974,16 @@ public expect fun <T> Sequence<T>.windowed(size: Int, step: Int): Sequence<List<
*
* Both [size] and [step] must be positive and can be greater than the number of elements in this sequence.
* @param size the number of elements to take in each window
* @param step the number of elements to move the window forward by on an each step
* @param step the number of elements to move the window forward by on an each step, by default 1
* @param partialWindows controls whether or not to keep partial windows in the end if any,
* by default `false` which means partial windows won't be preserved
*
* @sample samples.collections.Sequences.Transformations.averageWindows
*/
@SinceKotlin("1.2")
public expect fun <T, R> Sequence<T>.windowed(size: Int, step: Int, transform: (List<T>) -> R): Sequence<R>
public fun <T, R> Sequence<T>.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (List<T>) -> R): Sequence<R> {
return windowedSequence(size, step, partialWindows, reuseBuffer = true).map(transform)
}
/**
* Returns a sequence of pairs built from elements of both sequences with same indexes.
@@ -727,12 +727,16 @@ public expect inline fun String.partition(predicate: (Char) -> Boolean): Pair<St
*
* Both [size] and [step] must be positive and can be greater than the number of elements in this char sequence.
* @param size the number of elements to take in each window
* @param step the number of elements to move the window forward by on an each step
* @param step the number of elements to move the window forward by on an each step, by default 1
* @param partialWindows controls whether or not to keep partial windows in the end if any,
* by default `false` which means partial windows won't be preserved
*
* @sample samples.collections.Sequences.Transformations.takeWindows
*/
@SinceKotlin("1.2")
public expect fun CharSequence.windowed(size: Int, step: Int): List<String>
public fun CharSequence.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false): List<String> {
return windowed(size, step, partialWindows) { it.toString() }
}
/**
* Returns a list of results of applying the given [transform] function to
@@ -745,12 +749,26 @@ public expect fun CharSequence.windowed(size: Int, step: Int): List<String>
*
* Both [size] and [step] must be positive and can be greater than the number of elements in this char sequence.
* @param size the number of elements to take in each window
* @param step the number of elements to move the window forward by on an each step
* @param step the number of elements to move the window forward by on an each step, by default 1
* @param partialWindows controls whether or not to keep partial windows in the end if any,
* by default `false` which means partial windows won't be preserved
*
* @sample samples.collections.Sequences.Transformations.averageWindows
*/
@SinceKotlin("1.2")
public expect fun <R> CharSequence.windowed(size: Int, step: Int, transform: (CharSequence) -> R): List<R>
public fun <R> CharSequence.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (CharSequence) -> R): List<R> {
checkWindowSizeStep(size, step)
val thisSize = this.length
val result = ArrayList<R>((thisSize + step - 1) / step)
var index = 0
while (index < thisSize) {
val end = index + size
val coercedEnd = if (end > thisSize) { if (partialWindows) thisSize else break } else end
result.add(transform(subSequence(index, coercedEnd)))
index += step
}
return result
}
/**
* Returns a sequence of snapshots of the window of the given [size]
@@ -761,12 +779,16 @@ public expect fun <R> CharSequence.windowed(size: Int, step: Int, transform: (Ch
*
* Both [size] and [step] must be positive and can be greater than the number of elements in this char sequence.
* @param size the number of elements to take in each window
* @param step the number of elements to move the window forward by on an each step
* @param step the number of elements to move the window forward by on an each step, by default 1
* @param partialWindows controls whether or not to keep partial windows in the end if any,
* by default `false` which means partial windows won't be preserved
*
* @sample samples.collections.Sequences.Transformations.takeWindows
*/
@SinceKotlin("1.2")
public expect fun CharSequence.windowedSequence(size: Int, step: Int): Sequence<String>
public fun CharSequence.windowedSequence(size: Int, step: Int = 1, partialWindows: Boolean = false): Sequence<String> {
return windowedSequence(size, step, partialWindows) { it.toString() }
}
/**
* Returns a sequence of results of applying the given [transform] function to
@@ -779,12 +801,18 @@ public expect fun CharSequence.windowedSequence(size: Int, step: Int): Sequence<
*
* Both [size] and [step] must be positive and can be greater than the number of elements in this char sequence.
* @param size the number of elements to take in each window
* @param step the number of elements to move the window forward by on an each step
* @param step the number of elements to move the window forward by on an each step, by default 1
* @param partialWindows controls whether or not to keep partial windows in the end if any,
* by default `false` which means partial windows won't be preserved
*
* @sample samples.collections.Sequences.Transformations.averageWindows
*/
@SinceKotlin("1.2")
public expect fun <R> CharSequence.windowedSequence(size: Int, step: Int, transform: (CharSequence) -> R): Sequence<R>
public fun <R> CharSequence.windowedSequence(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (CharSequence) -> R): Sequence<R> {
checkWindowSizeStep(size, step)
val windows = (if (partialWindows) indices else 0 until length - size + 1) step step
return windows.asSequence().map { index -> transform(subSequence(index, (index + size).coerceAtMost(length))) }
}
/**
* Returns a list of pairs built from characters of both char sequences with same indexes. List has length of shortest char sequence.