diff --git a/src/main/kotlin/KotlinFunctionLibrary.kt b/src/main/kotlin/KotlinFunctionLibrary.kt index 674ad80..602ba02 100644 --- a/src/main/kotlin/KotlinFunctionLibrary.kt +++ b/src/main/kotlin/KotlinFunctionLibrary.kt @@ -920,10 +920,46 @@ println("workingList2=$workingList2")*/ * */ inline fun Iterable.findBy(key: R, selector: (T) -> R): T? = find { selector(it) == key } - + /** + * Returns a list of snapshots of windows whose every element returns true for + * [predicate](window, element) (meaning that every window matches the predicate). + * @see windowedByMaxLength + */ + fun Iterable.windowedBy(predicate: (window: List, element: T) -> Boolean): List> { + val result = mutableListOf>() + val copy = ArrayDeque(toList()) + while (copy.isNotEmpty()) { + val window = mutableListOf() + var first = copy.firstOrNull() + while (first != null && predicate(window, first)) { + window.add(first) + copy.removeFirst() + first = copy.firstOrNull() + } + result.add(window) + } + return result + } + /** + * Returns a list of windows, where each window's length (as defined by [getElementLength]) is at most [maxLength]. + */ + fun Iterable.windowedByMaxLength(maxLength: Int, getElementLength: (T) -> Int): List> { + var currentSumOfLengths = 0 + return windowedBy { window, element -> + val newLength = currentSumOfLengths + getElementLength(element) + val sameWindow = newLength < maxLength + currentSumOfLengths = if(sameWindow) newLength else 0 + sameWindow + } + } + /** + * Returns a list of windows, where every window's string's lengths add to at most [maxLength]. + * For example, ["a", "b", "c", "d"].windowedByMaxLength(2) == [[a,b], [c,d]] + */ + fun Iterable.windowedByMaxLength(maxLength: Int) = windowedByMaxLength(maxLength) { it.length } /** * Splits a list by a predicate. List analog to [String.split] - * */ + */ fun List.split(includeDelimiter: Boolean = false, predicate: (E) -> Boolean): List> { return flatMapIndexed { index, element -> when {