All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nield.kotlinstatistics.Bin.kt Maven / Gradle / Ivy

There is a newer version: 1.2.1
Show newest version
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)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy