Skip to content

Instantly share code, notes, and snippets.

@Miha-x64
Last active December 6, 2024 22:38
Show Gist options
  • Save Miha-x64/ec39faec7098fad2aaaa96bec87a52b8 to your computer and use it in GitHub Desktop.
Save Miha-x64/ec39faec7098fad2aaaa96bec87a52b8 to your computer and use it in GitHub Desktop.
@file:Suppress("UNCHECKED_CAST", "NAME_SHADOWING")
/**
* this.filterIndexed(inPredicate).mapIndexed(transform).filterIndexed(outPredicate).take(limit)
*/
inline fun <T, R> List<T>.mapFilterLimiting(
fromIndex: Int = 0,
toIndex: Int = size,
inPredicate: (index: Int, T) -> Boolean = { _: Any?, _: Any? -> true },
transform: (index: Int, T) -> R,
outPredicate: (index: Int, R) -> Boolean = { _: Any?, _: Any? -> true },
limit: Int = Int.MAX_VALUE,
): List<R> {
if (fromIndex < 0 || toIndex < fromIndex || toIndex > size) thrBadRange(fromIndex, toIndex, size)
if (limit < 0) thrNegLim(limit)
if (limit == 0 || fromIndex == toIndex) return emptyList()
var i = fromIndex
var ti = 0
var first: R? = null
i = search(
i, toIndex,
stop = { i -> get(i).let { inPredicate(i, it) && outPredicate(ti, transform(ti++, it).also { first = it }) } },
block = {},
missing = { return emptyList() },
)
if (limit == 1) return listOf(first as R)
var second: R? = null
i = search(
i, toIndex,
stop = { i -> get(i).let { inPredicate(i, it) && outPredicate(ti, transform(ti++, it).also { second = it }) } },
block = {},
missing = { return listOf(first as R) },
)
val destination = ArrayList<R>(minOf(toIndex - fromIndex, limit, 10)).also { it.add(first as R); it.add(second as R) }
var count = 2
i = search(
i, toIndex,
stop = { count == limit },
block = { i ->
val it = get(i)
if (inPredicate(i, it))
transform(ti, it).also { r ->
if (outPredicate(ti++, r)) {
destination.add(r)
count++
}
}
},
missing = {},
)
return destination
}
/**
* destination += this.filterIndexed(inPredicate).mapIndexed(transform).filterIndexed(outPredicate).take(limit)
*/
inline fun <C : MutableCollection<in R>, T, R> List<T>.mapFilterLimitingTo(
destination: C,
fromIndex: Int = 0,
toIndex: Int = size,
inPredicate: (index: Int, T) -> Boolean = { _: Any?, _: Any? -> true },
transform: (index: Int, T) -> R,
outPredicate: (index: Int, R) -> Boolean = { _: Any?, _: Any? -> true },
limit: Int = Int.MAX_VALUE,
): C {
if (fromIndex < 0 || toIndex < fromIndex || toIndex > size) thrBadRange(fromIndex, toIndex, size)
if (limit < 0) thrNegLim(limit)
if (limit == 0 || fromIndex == toIndex) return destination
var ti = 0
var count = 0
search(
fromIndex, toIndex,
stop = { count == limit },
block = { i ->
val it = get(i)
if (inPredicate(i, it))
transform(ti, it).also { r ->
if (outPredicate(ti++, r)) {
destination.add(r)
count++
}
}
},
missing = {},
)
return destination
}
/**
* this.filterIndexed(inPredicate).mapIndexed(transform).filterIndexed(outPredicate).take(limit)
*/
inline fun <T, R> Iterator<T>.mapFilterLimiting(
inPredicate: (index: Int, T) -> Boolean = { _: Any?, _: Any? -> true },
transform: (index: Int, T) -> R,
outPredicate: (index: Int, R) -> Boolean = { _: Any?, _: Any? -> true },
limit: Int = Int.MAX_VALUE,
): List<R> {
if (limit < 0) thrNegLim(limit)
if (limit == 0) return emptyList()
var i = 0
var ti = 0
var first: R? = null
while (true) {
if (!hasNext()) return emptyList()
val t = next()
if (inPredicate(i++, t) && outPredicate(ti, transform(ti++, t).also { first = it })) break
}
if (limit == 1) return listOf(first as R)
var second: R? = null
while (true) {
if (!hasNext()) return listOf(first as R)
val t = next()
if (inPredicate(i++, t) && outPredicate(ti, transform(ti++, t).also { second = it })) break
}
val destination = ArrayList<R>(minOf(limit, 10)).also { it.add(first as R); it.add(second as R) }
var count = 2
while (count < limit && hasNext()) {
val t = next()
if (inPredicate(i++, t))
transform(ti, t).also { r ->
if (outPredicate(ti++, r)) {
destination.add(r)
count++
}
}
}
return destination
}
/**
* destination += this.filterIndexed(inPredicate).mapIndexed(transform).filterIndexed(outPredicate).take(limit)
*/
inline fun <C : MutableCollection<in R>, T, R> Iterator<T>.mapFilterLimitingTo(
destination: C,
inPredicate: (index: Int, T) -> Boolean = { _: Any?, _: Any? -> true },
transform: (index: Int, T) -> R,
outPredicate: (index: Int, R) -> Boolean = { _: Any?, _: Any? -> true },
limit: Int = Int.MAX_VALUE,
): C {
if (limit < 0) thrNegLim(limit)
if (limit == 0) return destination
var i = 0
var ti = 0
var count = 0
while (count < limit && hasNext()) {
val t = next()
if (inPredicate(i++, t))
transform(ti, t).also { r ->
if (outPredicate(ti++, r)) {
destination.add(r)
count++
}
}
}
return destination
}
@PublishedApi internal fun thrBadRange(from: Int, to: Int, size: Int): Unit = // less bytecode than Nothing
throw IllegalArgumentException("Inapplicable range [$from, $to) for List[$size]")
@PublishedApi internal fun thrNegLim(limit: Int): Unit =
throw IllegalArgumentException("Negative limit: $limit")
@PublishedApi internal // dafuq?? wannabe private, it's inline after all
inline fun search(
from: Int, until: Int,
stop: (Int) -> Boolean, block: (Int) -> Unit, missing: () -> Unit,
): Int {
var i = from
while (i < until)
if (stop(i)) return i + 1 else block(i++)
missing()
return i
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment