Concise conversion of List<List<Double>> to Array<DoubleArray>? - kotlin

I wrote this in Kotlin:
fun fromLists(cells: List<List<Double>>): Matrix {
return Matrix(cells.stream()
.map { x -> x.toDoubleArray() }
.toArray { i: Int -> Array(i, { k: Int -> DoubleArray(k) }) } )
}
Is there any way to reduce repetition in this code?
(Matrix itself is uninteresting, it just wraps an Array<DoubleArray>)

val ex1: Array<DoubleArray> = cells.map { it.toDoubleArray() }.toTypedArray()
// this should be faster, it doesn't create extra List like the previous example
val ex2: Array<DoubleArray> = Array(cells.size) { i -> cells[i].toDoubleArray() }

Related

Create map from list of list

I want to create map from list of list and I have write this code
fun getCourses(coursesCount: Int): Map<Course, Int> {
val paidCourses = mutableMapOf<Course, Int>()
for(student in data) {
for(course in student.subscribedCourses) {
if( course.isPaid ) {
paidCourses.putIfAbsent(course, 0)
paidCourses[course] = paidCourses[course]!! + 1
}
}
}
return paidCourses.toList().sortedByDescending { (_, value) -> value }.take(coursesCount).toMap()
}
I wonder how can I concise this more in Kotlin.
You can do a flatMap to flatten the "students with courses" to just a single list of all the courses, filter by isPaid, group by each course, and use eachCount to count the courses.
val paidCourses =
data.flatMap { it.subscribedCourses }
.filter { it.isPaid }
.groupingBy { it }.eachCount()
Note that this will create multiple intermediate lists and loop through them multiple times, which may be undesirable. Here's a way that avoids this, and is still quite concise:
val paidCourses = mutableMapOf<Course, Int>()
for(student in data) {
for(course in student.subscribedCourses) {
if (course.isPaid) {
paidCourses.merge(course, 1, Int::plus)
}
}
}
You can also do:
val paidCourses = mutableMapOf<Course, Int>()
for(student in data) {
student.subscribedCourses.filter { it.isPaid }
.groupingBy { it }
.eachCountTo(paidCourses)
}
You can use merge to increment the frequency.
paidCourses.merge(course, 1, Int::plus)

Cast away nested Option in Kotlin arrow

I have a value with below type in my data class
Option<Option<List<Pair<String, Option<String>>>>>
How would I access the right-most Option<Sring>. I have tried with when expression like below
when(Option<Option<List<Pair<String, Option<String>>>>>) {
is Some -> when(Option<Option<List<Pair<String, Option<String>>>>>.t) {
is Some -> when(Option<List<Pair<String, Option<String>>>>.t) {
......
but it's not looking good. Is there any other way to cast away those Options
val t: Option<Option<List<Pair<String, Option<String>>>>> =
Some(Some(listOf(
Pair("a", Some("A")),
Pair("b", Some("B")),
Pair("c", None)
)))
val l = t.flatten()
.map { list ->
list.map { pair -> pair.second }
}
.getOrElse { emptyList() }
val first = l.getOrElse(0) { None }
val second = l.getOrElse(1) { None }
val missing = l.getOrElse(7) { None }
nested // Option<Option<List<Pair<String, Option<String>>>>>
.flatten() // Option<List<Pair<String, Option<String>>>>
.map { it.map { it.second() } } // Option<List<Option<String>>>
.sequence(Option.applicative()) // Option<Option<List<String>>>
.flatten() // Option<List<String>>
flatten gets rid of nested options, and sequence goes from List<Option<A>> to Option<List<A>>.

Function that takes variable number of typed args and a closure with same number of typed args?

I'd like to make a function that takes a variable number of arguments of different types, and a closure, and call the closure with the same number of arguments, each corresponding to a type in the original argument list:
fun <A, B, ...>mergeWhenValid(
arg1: Either<Problem, A>,
arg2: Either<Problem, B>,
...,
closure: (A, B, ...) -> T
): Either<Problem, T> {
// do stuff and call closure(a, b, ...)
}
How might I accomplish this?
If your mergeWhenValid just returns closure result if all eithers are right and firstProblem.left() otherwise, you should use Either.fx<Problem, T> instead of your function. Example:
Either.fx<Problem, String> { "${eitherInt.bind()} ${eitherDouble.bind()} ${eitherFloat.bind()}" }
If your logic is more complex and you need somehow handle all eithers, you can do it either by creating special merging DSL:
fun <R> mergeWhenValid(block: MergeWhenValidScope.() -> R): R = MergeWhenValidScope().block()
class EitherProblem<out T>(internal val either: Either<Problem, T>)
class MergeWhenValidScope {
private val eithers = mutableListOf<Either<Problem, *>>()
operator fun <T> Either<Problem, T>.component1(): EitherProblem<T> {
eithers += this
return EitherProblem(this)
}
private fun doStuff(): Option<Problem> {
// you can use `eithers` here and choose one of their problems or create a new one
// if you return None, it will assume that all `eithers` are right,
// otherwise, problem will be wrapped in Either and returned
return eithers.asSequence().mapNotNull { it.swap().getOrElse { null } }.firstOption()
}
fun <R> combine(block: CombinerScope.() -> R): Either<Problem, R> =
doStuff().map { it.left() }.getOrElse { CombinerScope.block().right() }
object CombinerScope {
operator fun <T> EitherProblem<T>.invoke() = either.getOrHandle {
error("Unexpected problem $it")
}
}
}
Use case:
mergeWhenValid {
val (int) = eitherInt
val (double) = eitherDouble
val (float) = eitherFloat
combine { "${int()} ${double()} ${float()}" }
}
Or by pipelining functions which add all your eithers to some object:
fun <T> mergeWhenValid() = MergeWhenValidInit<T>()
class MergeWhenValidInit<T> {
operator fun <A> invoke(either: Either<Problem, A>): MergeWhenValid<A, T, T> =
MergeWhenValid(either, listOf(either)) { it }
}
class MergeWhenValid<A, B, C>(
private val either: Either<Problem, A>,
private val eithers: List<Either<Problem, *>>,
private val previous: (B) -> C // is allowed to be called only if all `eithers` are right
) {
private fun doStuff(): Option<Problem> {
// you can use `eithers` here and choose one of their problems or create a new one
// if you return None, it will assume that all `eithers` are right,
// otherwise, problem will be wrapped in Either and returned
return eithers.asSequence().mapNotNull { it.swap().getOrElse { null } }.firstOption()
}
operator fun invoke(block: (A) -> B): Either<Problem, C> =
doStuff().map { it.left() }.getOrElse { requireC(block).right() }
operator fun <D> invoke(either: Either<Problem, D>): MergeWhenValid<D, (A) -> B, C> =
MergeWhenValid(either, eithers + either) { next -> requireC(next) }
private fun requireC(next: (A) -> B): C = previous(next(either.getOrHandle {
error("Unexpected problem $it")
}))
}
Use case:
mergeWhenValid<String>()(eitherInt)(eitherDouble)(eitherFloat)() { float ->
{ double -> { int -> "$int $double $float" } }
}
Note: the last approach reverses the order of arguments and also forces you to write { c -> { b -> { a -> ... } } } instead of { c, b, a -> ... }.

How can I check 2 conditions using let (or apply etc)

Is there a more idiomatic way to write the following?
foo?.let{
if(!foo.isBlank()) {
bar?.let {
if(!bar.isBlank()) {
println("foo and bar both valid strings")
}
}
}
}
basically this the idea is that both strings should be nonNull and nonEmpty and I was wondering if there is a more Kotlin way than doing if(foo.isNullOrEmpty && !bar.isNullOrEmpty)
Use this
fun <T, R, S> biLet(lhs: T, rhs: R, block: (T, R) -> S): S? = if (lhs != null && rhs != null) block(lhs, rhs) else null
Use as
biLet(foo, bar) { safeFoo, safeBar ->
}
Edit: variant for strings
fun <T: CharSequence?, S> biLet(lhs: T, rhs: T, block: (T, T) -> S): S? =
if (lhs.isNotNullOrBlank() && rhs.isNotNullOrBlank()) block(lhs, rhs) else null
You can use sequenceOf and none:
if (sequenceOf(foo, bar).none { it.isNullOrBlank() }) {
println("foo and bar both valid strings")
}
Declare somewhere an extension function using lambdas like:
inline fun String.ifNotEmpty(bar: String, function: () -> Unit) {
if (this.isNotEmpty() && bar.isNotEmpty()) {
function.invoke()
}
}
And use it as:
val foo = "foo-value"
val bar = "bar-value"
foo.ifNotEmpty(bar) {
println("foo and bar both valid strings")
}
Improving #Francesc answer, I created a nLet version
fun <S> nLet(vararg ts: Any?, block: (Array<out Any?>) -> S): S? =
if (ts.none { when (it) { is String -> it.isNullOrEmpty() else -> it == null } }) block(ts) else null
You can use it like that
nLet (1, 2 , 3, "a", "B", true) { ts ->
ts.forEach { println(it) }
}
This is what I use:
fun <P1, P2, R> nLet(p1: P1?, p2: P2?, block: (P1, P2) -> R?): R? =
p1?.let { p2?.let { block(p1, p2) } }
Usage:
nLet(foo, bar) { f, b -> doStuff(f, b) }
Add more nLet functions with more P's if more arguments are needed.
You can also use this for an arbitary number of arguments:
fun <P, R> nLet(vararg ts: P?, block: (Array<out P?>) -> R): R? =
ts.takeIf { it.none { it == null } }?.let { block(it) }
Usage:
nLet(foo, bar, dog) { (f, b, d) -> doStuff(f, b, d) }
This works, but f, b and d will have nullable types even though they cannot be null.
(There might be a clever way to solve that...)

Multidimensional '3D' Matrix in Kotlin

What will be the syntax of creating a 3D matrix in Kotlin. It's Java equivalent is as follows:
public static final int[][][] data = {{{0,0},{0}},{{0,1},{0}},{{1,0},{0}},{{1,1},{1}}};
Thanks
Edit:
Also how can I print the Kotlin code using the simple println?
When working with arrays in most languages I find it nice to create a helper class, rather than working directly with an int[][][] type. This way you can ensure certain invariants hold (such as all rows having the same length), and ensure better data locality. It can also let you efficiently implement certain operations such as slicing, sub-matrices, transpose etc.
My usual set of classes would look something like this for 3D. (though I'd probably template on the stored type, rather than hard code it for Int)
Its pretty incomplete, but the main at the end shows how many of the functions work.
But to show how you can create a 3D array from values you can do
val V = /* .. as in mEQ5aNLrK3lqs3kfSa5HbvsTWe0nIu's answer */
val M = Matrix3D(NX,NY,NZ).transform( { v, ix, iy, iz -> V[ix][iy][iz] } )
Further examples are
fun main(args: Array<String>) {
// Create an empty matrix
val v = Matrix3D(4,4,2);
// We can access elements via [a,b,c] or [a][b][c]
v[0,1,1] = 7;
print(v)
println("v[0,1,1]=" + v[0,1,1])
println("v[0][1][1]=" + v[0][1][1])
println("-----")
// Make the matrix a little more interesting
v.transform({ w,ix,iy,iz -> ix+iy+iz})
print(v)
println("-----")
// Transform just the slice with ix=2
// Slices are fast, as they copy no elements.
// but if you change them you change the original
v[2].transform({w,iy,iz -> w+3})
print(v)
// If you dont want to change the original you can always
// create an independent copy
print(v[2].bake().transform({w,iy,iz -> w-3}))
println("-----")
// W is the slice of v with ix=0
// Can easily extend the slicing options to allow slicing along
// any axis - I'd like to add v[_,1,_] to mean the slice with iy=1
// but I've not got to that yet.
val W = v[0]
print("W=\n")
print(v[0])
print("W^T=\n")
// Fast transpose, no elements are copied.
val WT=v[0].transpose()
print(WT)
// Changing the transpose slice writes back into the original
WT[1,1]=5
print(V)
}
fun print(M:Matrix3D) {
for(iz in 0..(M.nz-1)) {
for(iy in 0..(M.ny-1)) {
for(ix in 0..(M.nx-1)){
print("%d ".format(M[ix,iy,iz]))
}
print("\n")
}
print("\n")
}
}
fun print(M:Matrix2D) {
for(iy in 0..(M.ny-1)) {
for(ix in 0..(M.nx-1)){
print("%d ".format(M[ix,iy]))
}
print("\n")
}
}
The library code looks like this:
class Matrix1D(
val v:Array<Int>,
val nx:Int,
val offset:Int,
val xstride:Int) {
// TODO: Check that the nx,offset,strides etc are valid
constructor(nx:Int) : this(Array(nx,{i->0}), nx, 0, 1) {
}
fun offsetof(ix:Int):Int {
return offset + ix*xstride
}
operator fun get(ix:Int): Int {
return v[offsetof(ix)]
}
operator fun set(ix:Int, v:Int) {
this.v[offsetof(ix)] = v
}
fun reverse() : Matrix1D {
return Matrix1D(v, nx, offsetof(nx-1), -xstride)
}
fun submatrix(startx:Int, newNX:Int) : Matrix1D {
return Matrix1D(v,newNX,offsetof(startx), xstride)
}
fun transform(body: (Int, Int) -> Int ) {
for(ix in 0..(nx-1)){
this[ix] = body(this[ix], ix)
}
}
fun bake() : Matrix1D {
val rv = Matrix1D(nx);
for(ix in 0..(nx-1)) {
rv[ix] = this[ix]
}
return rv
}
}
class Matrix2D(
val v:Array<Int>,
val nx:Int, val ny:Int,
val offset:Int,
val xstride:Int, val ystride:Int) {
// TODO: Check that the nx,ny,offset,strides etc are valid
constructor(nx:Int, ny:Int) : this(Array(nx*ny,{i->0}), nx, ny, 0, 1, nx ) {
}
fun offsetof(ix:Int,iy:Int): Int {
return offset + ix*xstride + iy*ystride
}
operator fun get(ix:Int,iy:Int): Int {
return v[offsetof(ix,iy)]
}
operator fun set(ix:Int,iy:Int,v:Int) {
this.v[offsetof(ix,iy)] = v
}
operator fun get(ix:Int): Matrix1D {
return Matrix1D(v, ny, offsetof(ix,0), ystride)
}
fun transpose(): Matrix2D {
return Matrix2D(v,ny,nx,offset,ystride,xstride)
}
fun submatrix(startx:Int, starty:Int, newNX:Int, newNY:Int) : Matrix2D {
return Matrix2D(v,newNX,newNY,offsetof(startx,starty), xstride, ystride)
}
fun transform(body: (Int, Int, Int) -> Int ) {
for(iy in 0..(ny-1)) {
for(ix in 0..(nx-1)){
this[ix,iy] = body(this[ix,iy], ix,iy)
}
}
}
fun bake() : Matrix2D {
val rv = Matrix2D(nx,ny);
for(ix in 0..(nx-1)) {
for(iy in 0..(ny-1)) {
rv[ix,iy] = this[ix,iy]
}
}
return rv
}
}
class Matrix3D(
val v:Array<Int>,
val nx:Int, val ny:Int, val nz:Int,
val offset:Int,
val xstride:Int, val ystride:Int, val zstride:Int) {
// TODO: Check that the nx,ny,nz,offset,strides etc are valid
constructor(nx:Int, ny:Int, nz:Int) : this(Array(nx*ny*nz,{i->0}), nx, ny, nz, 0, 1, nx, nx*ny ) {
}
operator fun get(ix:Int,iy:Int,iz:Int): Int {
return v[offset + ix*xstride + iy*ystride + iz*zstride]
}
operator fun set(ix:Int,iy:Int,iz:Int, v:Int) {
this.v[offset + ix*xstride + iy*ystride + iz*zstride] = v
}
operator fun get(ix:Int): Matrix2D {
return Matrix2D(v, ny, nz, offset + ix*xstride, ystride, zstride )
}
fun transform(body: (Int, Int, Int, Int) -> Int ) {
for(iz in 0..(nz-1)) {
for(iy in 0..(ny-1)) {
for(ix in 0..(nx-1)){
this[ix,iy,iz] = body(this[ix,iy,iz], ix,iy,iz)
}
}
}
}
fun bake() : Matrix3D {
val rv = Matrix3D(nx,ny,nz);
for(ix in 0..(nx-1)) {
for(iy in 0..(ny-1)) {
for(iz in 0..(nz-1)){
rv[ix,iy,iz] = this[ix,iy,iz]
}
}
}
return rv
}
}
Kotlin currently does not support array literals.
You can use a combination of arrayOf() and intArrayOf():
val data = arrayOf(
arrayOf(intArrayOf(0, 0), intArrayOf(0)),
arrayOf(intArrayOf(0, 1), intArrayOf(0)),
arrayOf(intArrayOf(1, 0), intArrayOf(0)),
arrayOf(intArrayOf(1, 1), intArrayOf(1))
)
You can cut down a little bit on the verbosity using import aliasing if needed:
import kotlin.arrayOf as arr
import kotlin.intArrayOf as iarr
val data = arr(
arr(iarr(0, 0), iarr(0)),
arr(iarr(0, 1), iarr(0)),
arr(iarr(1, 0), iarr(0)),
arr(iarr(1, 1), iarr(1))
)
Also note that you can auto-convert Java code to Kotlin
in IntelliJ IDEA: copy Java code into a Kotlin file, a confirmation prompt will open.
online: using http://try.kotlinlang.org.
Using Multik
Multik Multidimensional array library for Kotlin.
Syntax for creating 3D array
mk.d3array(2, 2, 3) { it * it }
//output
/*[[[0, 1, 4],
[9, 16, 25]],
[[1, 0, 0],
[1, 1, 1]]]
*/
Note:Multik supports up to 4 dimensions
The Multik project’s GitHub repository
For more info check Jetbrain blog post