Fill missing data in a linear model - kotlin

I have the following val list = listOf(1, 2, 3, null, null, 6, 7) I'd like to fill the null value for the following result: listOf(1, 2, 3, 4, 5, 6, 7)
I couldn't find any method doing this in Kotlin, do you guys have an idea?
EDIT: I'm adding more details, the list will always have a beginning element and an ending element (ie no list as listOf(null, 2 ,3) or listOf(1, 2, null)) I preprocess this.
In my example I gave Integer element but it could be Float or Double

I've manage to do a simple function that could interpolate. There is room for improvement.
private fun Double.format(): String = DecimalFormat("#.##").format(this)
private fun List<*>.findNonNullIndex(currentIndex: Int, ascending: Boolean = true): Int {
for (i in currentIndex..lastIndex step if(ascending) 1 else -1) {
if(getOrNull(i) != null) return i
}
return currentIndex
}
fun interpolate(list: MutableList<Double>) {
println("initial : $list")
list.forEachIndexed { index, i ->
if(i == null) {
val nonNullIndex = list.findNonNullIndex(index)
val difference = list[nonNullIndex]?.minus(list[index-1] ?: return) ?: return
val coefficient = difference.div((nonNullIndex - index) + 1)
for(j in index until nonNullIndex) {
list[j] = (list[j-1]?.plus(coefficient))?.format()?.toDouble()
}
}
}
println("result: $list")
}
interpolate(mutableListOf(1.0, null, null, null, 1.4, null, 1.5, 1.7))
link: https://pl.kotl.in/HcqoB8qFL

Try this
inline fun <T>List<T?>.replaceIfNull(block:(T) -> T) : List<T>{
val temp = mutableListOf<T>()
for((index, element) in this.withIndex()){
if(element == null){
temp.add(block(this[index - 1] ?: temp[index - 1]))
} else {
temp.add(element)
}
}
return temp
}
fun main() {
val list = listOf(1, 2, 3, null, null, 6, 7)
val foo = list.replaceIfNull { nonNullValue ->
nonNullValue + 1
}
println(foo) // [1, 2, 3, 4, 5, 6, 7]
}
EDIT
Linear Model
fun <T:Number>List<T?>.interpolate() : List<Double> {
val temp = mutableListOf<Double>()
var nullCounter = 0
this.forEach { element ->
if(element != null){
val formatedElement = element.format()
temp.add(formatedElement)
if(nullCounter > 0){
var difference = (formatedElement - temp[temp.size - 2]) / (nullCounter + 1)
for(i in 0..nullCounter - 1){
val newElement = (temp[temp.size - 2] + difference).format()
temp.add((temp.size - 1), newElement)
}
}
nullCounter = 0
}
element ?: nullCounter++
}
return temp
}
test: https://pl.kotl.in/rpbDZ8zkq

There's no way on how to decide what number you want to replace with null.
Considering what if listOf(1, null, null) or listOf(null, 2, null).
If you know exactly what a list needs to be, you might use IntProgression or IntRange instead.
// 1, 2, 3, 4, 5, 6, 7
val list1 = IntRange(1, 7).toList()
// 1, 3, 5, 7
val list1 = IntProgression(1, 7, 2).toList()

Related

Unzip for Triple in Kotlin

In kotlin, if I have a pair I can get a list of first values and second values like this:
val(firstList, secondList) = listOfPairs.unzip()
// listOfPairs: List<Pair<String, Long>>
How can I do the same for a Triple?
How bout something like this:
fun <X>List<Triple<X,X,X>>.unzip(): List<List<X>> {
return fold(listOf(ArrayList<X>(), ArrayList<X>(), ArrayList<X>())){ r, i ->
r[0].add(i.first)
r[1].add(i.second)
r[2].add(i.third)
r
}
}
Usage:
val triplesList = listOf(Triple(1,"s",3), Triple(1,"u",3), Triple(1,"p",3))
val (listOne, listTwo, listThree) = triplesList.unzip()
println("ListOne: $listOne")
println("ListTwo: $listTwo")
println("ListThree: $listThree")
/* Output:
ListOne: [1, 1, 1]
ListTwo: [s, u, p]
ListThree: [3, 3, 3]
*/
Try it online!
How about this?
val firstList = listOf(triple1, triple2).map {it.first }
val secondList = listOf(triple1, triple2).map { it.second }
val thirdList = listOf(triple1, triple2).map { it.third }
or
val result = listOf(triple1, triple2).map {
Triple(it.first, it.second, it.third)
}

How can I take varying chunks out of a Kotlin Sequence?

If I have a Kotlin sequence, every invocation of take(n) restarts the sequence.
val items = generateSequence(0) {
if (it > 9) null else it + 1
}
#Test fun `take doesn't remember position`() {
assertEquals(listOf(0, 1), items.take(2).toList())
assertEquals(listOf(0, 1, 2), items.take(3).toList())
}
Is there an easy way of write say, another(n) such that
#Test fun `another does remember position`() {
assertEquals(listOf(0, 1), items.another(2).toList())
assertEquals(listOf(2, 3, 4), items.another(3).toList())
}
I suppose that I have to have something that isn't the Sequence to keep the state, so maybe what I'm actually asking for is a nice definition of fun Iterator<T>.another(count: Int): List<T>
Sequence does not remember its position, but its iterator does remember:
val iterator : Iterator<Int> = items.iterator()
Now all you need is something like take(n) but for Iterator<T>:
public fun <T> Iterator<T>.another(n: Int): List<T> {
require(n >= 0) { "Requested element count $n is less than zero." }
if (n == 0) return emptyList()
var count = 0
val list = ArrayList<T>(n)
for (item in this) {
list.add(item)
if (++count == n)
break
}
return list
}
What about this:
#Test
fun `another does remember position`() {
val items: Sequence<Int> = generateSequence(0) {
if (it > 9) null else it + 1
}
val (first, rest) = items.another(2)
assertEquals(listOf(0, 1), first.toList())
assertEquals(listOf(2, 3, 4), rest.another(3).first.toList())
}
fun <T> Sequence<T>.another(n: Int): Pair<Sequence<T>, Sequence<T>> {
return this.take(n) to this.drop(n)
}
To answer the last part of your question:
I suppose that I have to have something that isn't the Sequence to keep the state, so maybe what I'm actually asking for is a nice definition of fun Iterator.another(count: Int): List
One such implementation would be:
fun <T> Iterator<T>.another(count: Int): List<T> {
val collectingList = mutableListOf<T>()
while (hasNext() && collectingList.size < count) {
collectingList.add(next())
}
return collectingList.toList()
}
This passes your test if you use the iterator produced by the sequence:
#Test
fun `another does remember position`() {
val items = generateSequence(0) {
if (it > 9) null else it + 1
}.iterator() //Use the iterator of this sequence.
assertEquals(listOf(0, 1), items.another(2))
assertEquals(listOf(2, 3, 4), items.another(3))
}
To me what you've described is an iterator, since it's something that allows you to go over a collection or sequence etc. but also remember its last position.
NB the implementation above wasn't written to take into consideration what should happen for non-positive counts passed in, and if the count is larger than what's left to iterate over you'll be returned a list which has smaller size than n. I suppose you could consider this an exercise for yourself :-)
Sequence does not remember its position, but its iterator does remember:
val iterator : Iterator<Int> = items.iterator()
Unfortunately there is no take(n) for an iterator, so to use the one from stdlib you need to wrap iter into an Iterable:
val iterable : Iterable<Int> = items.iterator().asIterable()
fun <T> Iterator<T>.asIterable() : Iterable<T> = object : Iterable<T> {
private val iter = this#asIterable
override fun iterator() = iter
}
That makes itareble.take(n) remember its position, but unfortunately there is a of-by-one error because the standard .take(n) asks for one element too many:
public fun <T> Iterable<T>.take(n: Int): List<T> {
require(n >= 0) { "Requested element count $n is less than zero." }
if (n == 0) return emptyList()
if (this is Collection<T>) {
if (n >= size) return toList()
if (n == 1) return listOf(first())
}
var count = 0
val list = ArrayList<T>(n)
for (item in this) {
if (count++ == n)
break
list.add(item)
}
return list.optimizeReadOnlyList()
}
That can be fixed with a little tweak:
public fun <T> Iterable<T>.take2(n: Int): List<T> {
require(n >= 0) { "Requested element count $n is less than zero." }
if (n == 0) return emptyList()
if (this is Collection<T>) {
if (n >= size) return toList()
if (n == 1) return listOf(first())
}
var count = 0
val list = ArrayList<T>(n)
for (item in this) {
list.add(item)
//count++
if (++count == n)
break
}
return list
}
Now both of you tests pass:
#Test fun `take does not remember position`() {
assertEquals(listOf(0, 1), items.take2(2).toList())
assertEquals(listOf(0, 1, 2), items.take2(3).toList())
}
#Test fun `another does remember position`() {
assertEquals(listOf(0, 1), iter.take2(2).toList())
assertEquals(listOf(2, 3, 4), iter.take2(3).toList())
}
You could create a function generateStatefulSequence which creates a sequence which keeps its state by using a second sequence's iterator to provide the values.
The iterator is captured in the closure of that function.
On each iteration the seed lambda ({ i.nextOrNull() }) of the returned sequence starts off with the next value provided by the iterator.
// helper
fun <T> Iterator<T>.nextOrNull() = if(hasNext()) { next() } else null
fun <T : Any> generateStatefulSequence(seed: T?, nextFunction: (T) -> T?): Sequence<T> {
val i = generateSequence(seed) {
nextFunction(it)
}.iterator()
return generateSequence(
seedFunction = { i.nextOrNull() },
nextFunction = { i.nextOrNull() }
)
}
Usage:
val s = generateStatefulSequence(0) { if (it > 9) null else it + 1 }
println(s.take(2).toList()) // [0, 1]
println(s.take(3).toList()) // [2, 3, 4]
println(s.take(10).toList()) // [5, 6, 7, 8, 9, 10]
Try it out
Here is a nice definition of fun Iterator<T>.another(count: Int): List<T> as requested:
fun <T> Iterator<T>.another(count: Int): List<T> =
if (count > 0 && hasNext()) listOf(next()) + this.another(count - 1)
else emptyList()
As another workaround (similar to the suggestion by Willi Mentzel above) would be to create a asStateful() extension method that converts any sequence into a one that will remember the position, by wrapping it into an Iterable that always yields the same iterator.
class StatefulIterable<out T>(wrapped: Sequence<T>): Iterable<T> {
private val iterator = wrapped.iterator()
override fun iterator() = iterator
}
fun <T> Sequence<T>.asStateful(): Sequence<T> = StatefulIterable(this).asSequence()
Then you can do:
val items = generateSequence(0) {
if (it > 9) null else it + 1
}.asStateful()
#Test fun `stateful sequence does remember position`() {
assertEquals(listOf(0, 1), items.take(2).toList())
assertEquals(listOf(2, 3, 4), items.take(3).toList())
}
Try it here: https://pl.kotl.in/Yine8p6wn

doubleBinding has no effect

I'm taking my first experiment with TornadoFX and ran into a problem I don't understand.
I have an object Wind:
enum class Direction(val displayName: String, val abbrevation: String, val deltaX: Int, val deltaY: Int) {
NORTH("Észak", "É", 0, -1),
NORTH_EAST("Északkelet", "ÉK", 1, -1),
EAST("Kelet", "K", 1, 0),
SOUTH_EAST("Délkelet", "DK", 1, 1),
SOUTH("Dél", "D", 0, 1),
SOUTH_WEST("Délnyugat", "DNy", -1, 1),
WEST("Nyugat", "Ny", -1, 0),
NORTH_WEST("Északnyugat", "ÉNy", -1, -1);
val diagonal: Boolean = deltaX != 0 && deltaY != 0
val degree: Double = ordinal * 45.0
fun turnClockwise(eighth: Int = 1) = values()[(ordinal + eighth) umod 8]
fun turnCounterClockwise(eighth: Int = 1) = values()[(ordinal - eighth) umod 8]
fun turn(eighth: Int = 1) = if (eighth < 0) turnCounterClockwise(eighth.absoluteValue) else turnClockwise(eighth)
infix operator fun plus(eighth: Int) = turn(eighth)
infix operator fun minus(eighth: Int) = turn(-eighth)
infix operator fun minus(other: Direction) = (ordinal - other.ordinal) umod 8
}
object Wind {
val directionProperty = SimpleObjectProperty<Direction>(Direction.NORTH)
var direction: Direction
get() = directionProperty.value
set(value) {
println("SET WIND: $value")
directionProperty.value = value
}
}
I would like to bound a rotation transformation to the setting of wind direction.
When I use the old, JavaFX style, it works:
rot.angleProperty().bind(
createDoubleBinding(
Callable {
println("Direction: ${Wind.direction}");
Wind.directionProperty.value.degree * 45
},
Wind.directionProperty))
When I try to use the more elegant, Kotlin-style version, it doesn't bind:
rot.angleProperty().doubleBinding(rot.angleProperty() ) {
println("Direction: ${Wind.direction}")
Wind.directionProperty.value.degree * 45
}
Did I miss something?
The doubleBinding() function creates a Binding, but it does not bind it to anything.
In fact, we have two ways to create this binding:
doubleBinding(someProperty) { ... }. The operates on the property (this) and expects you to return a Double. It is not nullable.
someProperty.doubleBinding() { ... } receives the value as a parameter and expects you to return a Double. The parameter is nullable, so you need to account for that
That leaves you with two options:
rot.angleProperty().bind(doubleBinding(Wind.directionProperty) {
value.degree * 45
})
Or
rot.angleProperty().bind(Wind.directionProperty.doubleBinding {
it?.degree ?: 0.0 * 45
})
Which one you choose is mostly a matter of taste, though one will be more natural than the other in some cases.

How to sum multiple elements after grouping in Kotlin

I have a list of objects A (alist).
A {
val b : Int
val c1 : Int
val c2 : Int
val d1 : Int
val d2 : Int
}
and I want to group them by b and calculate sum of c1+c2 and d1+d2 on each group and put the results in list of E objects elist.
E {
val sum_of_c_types : Int
val sum_of_d_types : Int
}
How do I achieve in kotlin using any collection inbuilt function?
note:
I know I can do it with reduce function and create temporary A objects, but this is important to dont use temporary A object in code.
I've solved it by using a sequence of groupBy, map and sumBy. It's probably not the cleanest solution I guess.
data class A(val b: Int,
val c1: Int,
val c2: Int,
val d1: Int,
val d2: Int)
data class E(val sumC: Int, val sumD: Int)
fun main(args: Array<String>) {
val alist = listOf(A(1, 2, 1, 4, 5), A(1, 3, 4, 6, 3), A(2, 2, 2, 2, 2), A(3, 1, 2, 1, 2))
val grouped: Map<Int, E> = alist.groupBy(A::b).mapValues {
E(it.value.sumBy { it.c1 + it.c2 }, it.value.sumBy { it.d1 + it.d2 })
}
grouped.forEach {
println("Group b=${it.key}: ${it.value}")
}
}
Results in:
Group b=1: E(sumC=10, sumD=18)
Group b=2: E(sumC=4, sumD=4)
Group b=3: E(sumC=3, sumD=3)
Edit:
With Grouping (using groupingBy instead of groupBy), it looks even better because you don't have to handle map entities:
val grouped = alist.groupingBy(A::b).aggregate { _, acc: E?, e, _ ->
E((acc?.sumC ?: 0) + e.c1 + e.c2, (acc?.sumD ?: 0) + e.d1 + e.d2)
}
I think it's just grouping with folding
fun group(a: List<A>) = a.groupingBy(A::b).fold(E(0, 0),
{ acc, elem ->
E(acc.sum_of_c_types + elem.c1 + elem.c2,
acc.sum_of_d_types + elem.d1 + elem.d2)
})
I solved it by following code:
alist.groupby { b }. mapValues {
it.value.map {
E(it.c1+it.c2, it.d1+it.d2)
}.reduce {
acc, e -> E(acc.sum_of_c_types + e.sum_of_c_types, acc.sum_of_d_types + e.sum_of_d_types)
}.values

Kotlin: Convert large List to sublist of set partition size

I'm looking for a function equivalent to Groovy's collate which would partition a large List into batches for processing. I did see subList which could be adapted into a similar function but wanted to check and make sure I wasn't missing an in-built or crazy simple alternative to rolling my own.
With Kotlin 1.3, according to your needs, you may choose one of the following ways to solve your problem.
#1. Using chunked
fun main() {
val list = listOf(2, 4, 3, 10, 8, 7, 9)
val newList = list.chunked(2)
//val newList = list.chunked(size = 2) // also works
print(newList)
}
/*
prints:
[[2, 4], [3, 10], [8, 7], [9]]
*/
#2. Using windowed
fun main() {
val list = listOf(2, 4, 3, 10, 8, 7, 9)
val newList = list.windowed(2, 2, true)
//val newList = list.windowed(size = 2, step = 2, partialWindows = true) // also works
println(newList)
}
/*
prints:
[[2, 4], [3, 10], [8, 7], [9]]
*/
NOTE: For Kotlin 1.2 and newer, please see the chunked and windowed functions that are now in the standard library. There is no need for a custom solution.
Here is an implementation of a lazy batching extension function which will take a collection, or anything that can become a Sequence and return a Sequence of List each of that size, with the last one being that size or smaller.
Example usage to iterate a list as batches:
myList.asSequence().batch(5).forEach { group ->
// receive a Sequence of size 5 (or less for final)
}
Example to convert batches of List to Set:
myList.asSequence().batch(5).map { it.toSet() }
See the first test case below for showing the output given specific input.
Code for the function Sequence<T>.batch(groupSize):
public fun <T> Sequence<T>.batch(n: Int): Sequence<List<T>> {
return BatchingSequence(this, n)
}
private class BatchingSequence<T>(val source: Sequence<T>, val batchSize: Int) : Sequence<List<T>> {
override fun iterator(): Iterator<List<T>> = object : AbstractIterator<List<T>>() {
val iterate = if (batchSize > 0) source.iterator() else emptyList<T>().iterator()
override fun computeNext() {
if (iterate.hasNext()) setNext(iterate.asSequence().take(batchSize).toList())
else done()
}
}
}
Unit tests proving it works:
class TestGroupingStream {
#Test fun testConvertToListOfGroupsWithoutConsumingGroup() {
val listOfGroups = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).asSequence().batch(2).toList()
assertEquals(5, listOfGroups.size)
assertEquals(listOf(1,2), listOfGroups[0].toList())
assertEquals(listOf(3,4), listOfGroups[1].toList())
assertEquals(listOf(5,6), listOfGroups[2].toList())
assertEquals(listOf(7,8), listOfGroups[3].toList())
assertEquals(listOf(9,10), listOfGroups[4].toList())
}
#Test fun testSpecificCase() {
val originalStream = listOf(1,2,3,4,5,6,7,8,9,10)
val results = originalStream.asSequence().batch(3).map { group ->
group.toList()
}.toList()
assertEquals(listOf(1,2,3), results[0])
assertEquals(listOf(4,5,6), results[1])
assertEquals(listOf(7,8,9), results[2])
assertEquals(listOf(10), results[3])
}
fun testStream(testList: List<Int>, batchSize: Int, expectedGroups: Int) {
var groupSeenCount = 0
var itemsSeen = ArrayList<Int>()
testList.asSequence().batch(batchSize).forEach { groupStream ->
groupSeenCount++
groupStream.forEach { item ->
itemsSeen.add(item)
}
}
assertEquals(testList, itemsSeen)
assertEquals(groupSeenCount, expectedGroups)
}
#Test fun groupsOfExactSize() {
testStream(listOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15), 5, 3)
}
#Test fun groupsOfOddSize() {
testStream(listOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18), 5, 4)
testStream(listOf(1,2,3,4), 3, 2)
}
#Test fun groupsOfLessThanBatchSize() {
testStream(listOf(1,2,3), 5, 1)
testStream(listOf(1), 5, 1)
}
#Test fun groupsOfSize1() {
testStream(listOf(1,2,3), 1, 3)
}
#Test fun groupsOfSize0() {
val testList = listOf(1,2,3)
val groupCountZero = testList.asSequence().batch(0).toList().size
assertEquals(0, groupCountZero)
val groupCountNeg = testList.asSequence().batch(-1).toList().size
assertEquals(0, groupCountNeg)
}
#Test fun emptySource() {
listOf<Int>().asSequence().batch(1).forEach { groupStream ->
fail()
}
}
}
A more simplistic/functional-style solution would be
val items = (1..100).map { "foo_${it}" }
fun <T> Iterable<T>.batch(chunkSize: Int) =
withIndex(). // create index value pairs
groupBy { it.index / chunkSize }. // create grouping index
map { it.value.map { it.value } } // split into different partitions
items.batch(3)
Note 1: Personally I'd prefer partition as a method name here, but it's already present in Kotlin's stdlib to separate a lists into 2 parts given a predicate.
Note 2: The the iterator solution from Jayson may scale better than this solution for large collections.
In Kotlin 1.2 M2 and later you can use chunked and windowed (see Kotlin 1.2 M2 is out | Kotlin Blog). Note that there are Sequence variances too (see kotlin.sequences - Kotlin Programming Language).
For versions of Kotlin prior to 1.2 M2 I recommend using Lists.partition(List, int) from google-guava (it uses java.util.List.subList(int, int)):
If you are unfamiliar with Guava see CollectionUtilitiesExplained · google/guava Wiki for more details.
You can create your own Kotlin extension function for it if you want:
fun <T> List<T>.collate(size: Int): List<List<T>> = Lists.partition(this, size)
If you want an extension function for mutable lists then in a separate Kotlin file (to avoid platform declaration clashes):
fun <T> MutableList<T>.collate(size: Int): List<MutableList<T>> = Lists.partition(this, size)
If you want something lazy loaded like in Jayson Minard's answer you can use Iterables.partition(Iterable, int). You might also be interested in Iterables.paddedPartition(Iterable, int) if you want to pad the last sublist if it is smaller than the specified size. These return Iterable<List<T>> (I don't see much point in making it Iterable<Iterable<T>> as subList returns an efficient view).
If for some reason you don't want to depend on Guava you can roll your own pretty easily using the subList function you mentioned:
fun <T> List<T>.collate(size: Int): List<List<T>> {
require(size > 0)
return if (isEmpty()) {
emptyList()
} else {
(0..lastIndex / size).map {
val fromIndex = it * size
val toIndex = Math.min(fromIndex + size, this.size)
subList(fromIndex, toIndex)
}
}
}
or
fun <T> List<T>.collate(size: Int): Sequence<List<T>> {
require(size > 0)
return if (isEmpty()) {
emptySequence()
} else {
(0..lastIndex / size).asSequence().map {
val fromIndex = it * size
val toIndex = Math.min(fromIndex + size, this.size)
subList(fromIndex, toIndex)
}
}
}
Dummy Array
for (i in 0..49){
var data="java"
}
array.add(data)
Used:
var data=array?.chunked(15)
kotlin's method
There is unfortunately no built-in function for that yet and while functional and Sequence-based implementations from other answers look nice, if you just need is List of Lists, I'd suggest writing a little bit of ugly, imperative, but performant code.
This is my final result:
fun <T> List<T>.batch(chunkSize: Int): List<List<T>> {
if (chunkSize <= 0) {
throw IllegalArgumentException("chunkSize must be greater than 0")
}
val capacity = (this.size + chunkSize - 1) / chunkSize
val list = ArrayList<ArrayList<T>>(capacity)
for (i in 0 until this.size) {
if (i % chunkSize == 0) {
list.add(ArrayList(chunkSize))
}
list.last().add(this.get(i))
}
return list
}