org.nield.kotlinstatistics.BigDecimalStatistics.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 java.math.BigDecimal
import java.util.concurrent.atomic.AtomicBoolean
fun Sequence.sum() = fold(BigDecimal.ZERO) { x,y -> x + y }!!
fun Iterable.sum() = fold(BigDecimal.ZERO) { x,y -> x + y }!!
fun Sequence.average() = toList().let { list ->
list.sum() / BigDecimal.valueOf(list.count().toDouble())
}
fun Iterable.average() = asSequence().average()
// AGGREGATION OPERATORS
inline fun Sequence.sumBy(crossinline keySelector: (T) -> K, crossinline bigDecimalSelector: (T) -> BigDecimal) =
groupApply(keySelector, bigDecimalSelector) { it.sum() }
inline fun Iterable.sumBy(crossinline keySelector: (T) -> K, crossinline bigDecimalSelector: (T) -> BigDecimal) =
asSequence().sumBy(keySelector, bigDecimalSelector)
fun Sequence>.sumBy() =
groupApply({it.first}, {it.second}) { it.sum() }
fun Iterable>.sumBy() = asSequence().sumBy()
inline fun Sequence.averageBy(crossinline keySelector: (T) -> K, crossinline bigDecimalSelector: (T) -> BigDecimal) =
groupApply(keySelector, bigDecimalSelector) { it.average() }
inline fun Iterable.averageBy(crossinline keySelector: (T) -> K, crossinline bigDecimalSelector: (T) -> BigDecimal) =
asSequence().averageBy(keySelector, bigDecimalSelector)
fun Sequence>.averageBy() =
groupApply({it.first}, {it.second}) { it.average() }
fun Iterable>.averageBy() = asSequence().averageBy()
// bin operators
inline fun Sequence.binByBigDecimal(binSize: BigDecimal,
gapSize: BigDecimal,
crossinline valueSelector: (T) -> BigDecimal,
rangeStart: BigDecimal? = null
) = toList().binByBigDecimal(binSize, gapSize, valueSelector, { it }, rangeStart)
inline fun Sequence.binByBigDecimal(binSize: BigDecimal,
gapSize: BigDecimal,
crossinline valueSelector: (T) -> BigDecimal,
crossinline groupOp: (List) -> G,
rangeStart: BigDecimal? = null
) = toList().binByBigDecimal(binSize, gapSize, valueSelector, groupOp, rangeStart)
inline fun Iterable.binByBigDecimal(binSize: BigDecimal,
gapSize: BigDecimal,
crossinline valueSelector: (T) -> BigDecimal,
rangeStart: BigDecimal? = null
) = toList().binByBigDecimal(binSize, gapSize, valueSelector, { it }, rangeStart)
inline fun Iterable.binByBigDecimal(binSize: BigDecimal,
gapSize: BigDecimal,
crossinline valueSelector: (T) -> BigDecimal,
crossinline groupOp: (List) -> G,
rangeStart: BigDecimal? = null
) = toList().binByBigDecimal(binSize, gapSize, valueSelector, groupOp, rangeStart)
inline fun List.binByBigDecimal(binSize: BigDecimal,
gapSize: BigDecimal,
crossinline valueSelector: (T) -> BigDecimal,
rangeStart: BigDecimal? = null
): BinModel, BigDecimal> = binByBigDecimal(binSize, gapSize, valueSelector, { it }, rangeStart)
inline fun List.binByBigDecimal(binSize: BigDecimal,
gapSize: BigDecimal,
crossinline valueSelector: (T) -> BigDecimal,
crossinline groupOp: (List) -> G,
rangeStart: BigDecimal? = 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 isFirst = AtomicBoolean(true)
while (currentRangeEnd < maxC) {
currentRangeEnd = currentRangeStart + binSize - if (isFirst.getAndSet(false)) BigDecimal.ZERO else gapSize
add(currentRangeStart..currentRangeEnd)
currentRangeStart = currentRangeEnd + gapSize
}
}
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)
}