org.nield.kotlinstatistics.Bin.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-statistics Show documentation
Show all versions of kotlin-statistics Show documentation
Statistical and analytical extensions for Kotlin
package org.nield.kotlinstatistics
import org.nield.kotlinstatistics.range.Range
import org.nield.kotlinstatistics.range.until
import java.util.concurrent.atomic.AtomicBoolean
class Bin>(val range: Range, val value: T) {
operator fun contains(key: C) = key in range
override fun toString(): String {
return "Bin(range=$range, value=$value)"
}
}
class BinModel>(val bins: List>): Iterable> by bins {
operator fun get(key: C) = bins.find { key in it.range }
operator fun contains(key: C) = bins.any { key in it.range }
override fun toString(): String {
return "BinModel(bins=$bins)"
}
}
inline fun > List.binByComparable(binIncrements: Int,
crossinline incrementer: (C) -> C,
crossinline valueSelector: (T) -> C,
rangeStart: C? = null) = binByComparable(binIncrements, incrementer, valueSelector, { it }, rangeStart)
inline fun , G> List.binByComparable(binIncrements: Int,
crossinline incrementer: (C) -> C,
crossinline valueSelector: (T) -> C,
crossinline groupOp: (List) -> G,
rangeStart: C? = null
): BinModel {
val groupedByC = asSequence().groupBy(valueSelector)
val minC = rangeStart?:groupedByC.keys.min()!!
val maxC = groupedByC.keys.max()!!
val bins = mutableListOf>().apply {
var currentRangeStart = minC
var currentRangeEnd = minC
val initial = AtomicBoolean(true)
while (currentRangeEnd < maxC) {
repeat(if (initial.getAndSet(false)) binIncrements - 1 else binIncrements) { currentRangeEnd = incrementer(currentRangeEnd) }
add(currentRangeStart until currentRangeEnd)
currentRangeStart = incrementer(currentRangeEnd)
}
}
return bins.asSequence()
.map { it to mutableListOf() }
.map { binWithList ->
groupedByC.entries.asSequence()
.filter { it.key in binWithList.first }
.forEach { binWithList.second.addAll(it.value) }
binWithList
}.map { Bin(it.first, groupOp(it.second)) }
.toList()
.let(::BinModel)
}
inline fun > Sequence.binByComparable(binIncrements: Int,
crossinline incrementer: (C) -> C,
crossinline valueSelector: (T) -> C,
rangeStart: C? = null) = binByComparable(binIncrements, incrementer, valueSelector, { it }, rangeStart)
inline fun , G> Sequence.binByComparable(binIncrements: Int,
crossinline incrementer: (C) -> C,
crossinline valueSelector: (T) -> C,
crossinline groupOp: (List) -> G,
rangeStart: C? = null) = toList().binByComparable(binIncrements, incrementer, valueSelector, groupOp, rangeStart)