Skip to content

Commit fd838f7

Browse files
Add Iterable.windowedBy{}
1 parent b9d6cfa commit fd838f7

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

src/main/kotlin/KotlinFunctionLibrary.kt

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -920,10 +920,46 @@ println("workingList2=$workingList2")*/
920920
* */
921921
inline fun <T, R> Iterable<T>.findBy(key: R, selector: (T) -> R): T? = find { selector(it) == key }
922922

923-
923+
/**
924+
* Returns a list of snapshots of windows whose every element returns true for
925+
* [predicate](window, element) (meaning that every window matches the predicate).
926+
* @see windowedByMaxLength
927+
*/
928+
fun <T> Iterable<T>.windowedBy(predicate: (window: List<T>, element: T) -> Boolean): List<List<T>> {
929+
val result = mutableListOf<List<T>>()
930+
val copy = ArrayDeque(toList())
931+
while (copy.isNotEmpty()) {
932+
val window = mutableListOf<T>()
933+
var first = copy.firstOrNull()
934+
while (first != null && predicate(window, first)) {
935+
window.add(first)
936+
copy.removeFirst()
937+
first = copy.firstOrNull()
938+
}
939+
result.add(window)
940+
}
941+
return result
942+
}
943+
/**
944+
* Returns a list of windows, where each window's length (as defined by [getElementLength]) is at most [maxLength].
945+
*/
946+
fun <T> Iterable<T>.windowedByMaxLength(maxLength: Int, getElementLength: (T) -> Int): List<List<T>> {
947+
var currentSumOfLengths = 0
948+
return windowedBy { window, element ->
949+
val newLength = currentSumOfLengths + getElementLength(element)
950+
val sameWindow = newLength < maxLength
951+
currentSumOfLengths = if(sameWindow) newLength else 0
952+
sameWindow
953+
}
954+
}
955+
/**
956+
* Returns a list of windows, where every window's string's lengths add to at most [maxLength].
957+
* For example, ["a", "b", "c", "d"].windowedByMaxLength(2) == [[a,b], [c,d]]
958+
*/
959+
fun Iterable<CharSequence>.windowedByMaxLength(maxLength: Int) = windowedByMaxLength(maxLength) { it.length }
924960
/**
925961
* Splits a list by a predicate. List analog to [String.split]
926-
* */
962+
*/
927963
fun <E> List<E>.split(includeDelimiter: Boolean = false, predicate: (E) -> Boolean): List<List<E>> {
928964
return flatMapIndexed { index, element ->
929965
when {

0 commit comments

Comments
 (0)