I have a map whose values are an arraylist of different object types (LocalDate, LocalTime, Float, List(Float)).
I would like to transform the map values to a custom data class i have created.
I have tried destructuring the maps value components however i am getting error "Destructuring declaration initializer of type Map.Entry<String, Any> must have a 'component3()' function".
How would i perform this transformation below?
Blockquote
val localDate1 = LocalDate.now()
val localTime1 = LocalTime.now()
val float1 = 1f
val floatList1 = listOf<Float>(1f, 2f, 3f)
val localDate2 = LocalDate.now()
val localTime2 = LocalTime.now()
val float2 = 2f
val floatList2 = listOf<Float>(4f, 5f, 6f)
val myMap = HashMap<String, Any>()
myMap["keyOne"] = arrayListOf<Any>(localDate1, localTime1, float1, floatList1)
myMap["keyTwo"] = arrayListOf<Any>(localDate2, localTime2, float2, floatList2)
val newMap = myMap.mapValues { (date, time, float, floatList) -> /*Here i am getting destructuring error*/
CustomObject(
date,
time,
float,
floatList
)
}
Blockquote
data class CustomObject (
val date: LocalDate,
val time: LocalTime,
val float: Float,
val floatList: List<Float>
)
Map.mapValues() takes a lambda whose receiver is the map Entry, not its value. (The method is named for the lambda's results, not its parameter.) So you can't destructure it that way.
There are also typecasting issues: myMap is a map whose values are Any, but you seem to be assuming that each value is actually a List of Any (with the actual elements being of the appropriate types in the appropriate order). So you need to do the necessary casting to tell the compiler what types they are (or at least, what types you assume they are…)
So you could destructure it as a separate step, e.g.:
val newMap = myMap.mapValues { entry ->
val (date, time, float, floatList) = entry.value as List<Any>
CustomObject(
date as LocalDate,
time as LocalTime,
float as Float,
floatList as List<Float>
)
}
Or you could just use the array values directly:
val newMap = (myMap as Map<String, List<Any>>).mapValues {
CustomObject(
it.value[0] as LocalDate,
it.value[1] as LocalTime,
it.value[2] as Float,
it.value[3] as List<Float>
)
}
However I think it would be a lot better to avoid having the lists in the first place. You're taking a lot of extra code to create the lists and then convert them — but much of that code is unsafe: each destructuring can fail with an exception (perhaps ArrayIndexOutOfBoundsException) if the list isn't long enough, and each cast can fail with a ClassCastException. Casts are always a code smell, especially unchecked ones like these; Kotlin's type system is powerful enough to express most things you're likely to want, so bypassing it like this tends to indicate that the design can be improved.
So if there's any way you can create your custom objects directly, that's likely to be shorter, safer, faster, and easier to read.
import java.time.LocalDate
import java.time.LocalTime
data class CustomObject(
val date: LocalDate,
val time: LocalTime,
val float: Float,
val floatList: List<Float>
)
val myMap = mapOf(
"keyOne" to listOf(LocalDate.now(), LocalTime.now(), 1f, listOf(1f, 2f, 3f)),
"keyTwo" to listOf(LocalDate.now(), LocalTime.now(), 2f, listOf(4f, 5f, 6f))
)
val newMap = myMap.mapValues {
CustomObject(
it.value[0] as LocalDate,
it.value[1] as LocalTime,
it.value[2] as Float,
(it.value[3] as List<*>).map { fl -> fl as Float }
)
}
println(newMap)
Im just working through some simple practice problems in kotlin. In my code below I'm taking a number and attempting to add the number members together. Ex. 29, return 2 + 9 = 11. There could be a better way to accomplish this but, I'm taking the numbers, converting to string, and then putting them into a list, ie ["2","9"] when I attempt to convert list[0].toInt() it returns 50. It appears there is some rounding taking place but I have not found another kotlin method to work with. Can anyone offer some insights? TIA
fun main(args: Array<String>) {
fun addTwoDigits(n: Int): Int {
val sliced = n.toString().toList()
val int1 = sliced[0].toInt()
println(sliced[0]) //returns "2"
println(int1) // returns 50
return sliced[0].toInt() + sliced[1].toInt()
}
println(addTwoDigits(29))
}
Koltin Char.toString(), which you are using in line:
val int1 = sliced[0].toInt()
converts the character using the ASCII Code table.
You can simply add a toString() call before the toInt() call:
val int1 = sliced[0].toString().toInt()
I have been reviewing the documentation of apache commons math and I find that it also calculates distributions, but I can not understand how it works.
I have two values
degrees of freedom = 13
confidence interval = 0.95
My problem is that it does not yield the value I need,
The objective is:
result = 1.771
import org.apache.commons.math3.distribution.TDistribution
fun calculo(a:Double, b:Double): Double {
val distf = TDistribution(a,b)
return distf.getNumericalMean()
}
fun main(args: Array<String>) {
val ko = calculo(13,0.95)
println(ko)
}
```
You can use the following:
new org.apache.commons.math3.distribution.TDistribution(deg_freedom).
inverseCumulativeProbability(probability)
Where deg_freedom=13, and probability=0.95.
I have a question about Kotlin.
I tried two versions of Kotlin, 1.0.0 and 1.2.6.
Using Kotlin, we can initialize an array and access to its element like this.
val n: Int = 10
val arr = Array(n, { it } )
val i: Int = 0
println(arr[i])
However, I got an error with this code.
val n: Long = 10
val arr = Array(n, { it } )
val i: Long = 0
println(arr[i])
It seems that it is an only way to cast Long to Int in order to compile this code.
val n: Long = 10
val arr = Array(n.toInt(), { it } )
val i: Long = 0
println(arr[i.toInt()])
However, it seems too redundant to me, but I couldn't find any solutions. So my question is
Is there any way to initialize arrays and access elements with a Long
variable?
Does Kotlin have any reasons that Long variable should not be accepted here?
Kotlin comes with longArrayOf(1, 2, 3) which will create an array for you which contains Longs.
Note that what you are trying to do with println(arr[i]) is getting a Long value out of arr, but the indexing of arrays is done with Ints. It will never work with Longs:
/**
* Returns the array element at the given [index].
* This method can be called using the index operator.
*/
public operator fun get(index: Int): Long
If you want to initialize an array of longs of the given length, you can use the same top-level Array function:
val n = 10 // n is Int
val arrayOfLongs = Array(n) { it.toLong() } // Array of 10 longs
Here the number n is Int and the initializer function converts the integer index it of an element being initialized to Long, therefore we get an array of longs as the result.
Or you can use another similar function to create a specialized LongArray:
val longArray = LongArray(n) { it.toLong() } // LongArray of 10 longs
Both arrays store longs, but the latter does it more compactly.
What should I write in the place of area.toFixed(2)
fun main(args: Array<String>) {
val a = 20
val h = 30
val area = a * h / 2
println("Triangle area = ${area.toFixed(2)}")
}
I think you really meet a problem that how to convert Javascript code to Kotlin code. You need to ask the question clearly at next time, :). you can use String#format instead, for example:
println("%.2f".format(1.0)) // print "1.00"
println("%.2f".format(1.253)) // print "1.25"
println("%.2f".format(1.255)) // print "1.26"
AND the area is an Int which means it will truncates the precision, Kotlin doesn't like as Javascript use the numeric by default, so you should let a*h divide by a Double, then your code is like as below:
// v--- use a `Double` instead
val area = a * h / 2.0
println("Triangle area = ${"%.2f".format(area)}")