Kotlin JS - string to number conversion? - kotlin

How to do String to number conversion in Kotlin JS app. I am Using the following code and having some trouble converting from the HTMLInputElement value to double.
fun c2f(self: Any) {
console.log("Self object: ${self} ")
val celsius = document.getElementById("celcius")?.getAttribute("value") as Double
val fahrenheit = celsius * 1.8 + 32
console.log("Fahrenheit value: ${fahrenheit} ")
window.alert("Celcius (${celsius}) -> Fahrenheit (${fahrenheit}) ")
}
Also i am not seeing any toDouble() function on String class as in the case of JVM app.

Answering my own question as this would be helpful for somebody.
You can use the kotlin.js top level parse functions for string <-> Number conversion.
fun parseInt(s: String, radix: Int = 10): Int
fun safeParseInt(s : String) : Int?
fun safeParseDouble(s : String) : Double?

Simply use the String.toXXX() functions, e.g.
val n = "1"
val m = 2 + n.toInt()
val x = "1.1"
val y = 2.0 + x.toFloat()
etc.

Related

How to define function, which accepts all numerics in Kotlin

What I thought didn't work
fun compute1(x: Double, y:Double) : Double {
return x + y
}
fun compute2(x: Number, y:Number) : Number {
return x + y // can't use plus
}
fun main() {
compute1(12, 13) // cant use integers
}
How to accomplish?
Solution should be as laconic as in java
public class MathEx {
public static double compute(double x, double y) {
return x+y;
}
}
You could overload the function to receive the combinations that you want
fun compute(x:Double, y:Double) = x + y
fun compute(x:Float, y:Float) = x + y
fun compute(x:Int, y:Int) = x + y
fun compute(x:Double, y:Int) = x + y
fun compute(x:Float, y:Int) = x + y
fun main() {
compute(12, 13)
}
Quite verbose, or you can define just one or two and convert the number before calling the function, which is not very efficient but it would work
fun compute(x:Double, y:Double) = x + y
fun main() {
compute(12.toDouble(), 13.toDouble())
}
from https://kotlinlang.org/docs/basic-types.html#floating-point-types
Note that unlike some other languages, there are no implicit widening conversions for numbers in Kotlin. For example, a function with a Double parameter can be called only on Double values, but not Float, Int, or other numeric values.
It's not a perfect solution since there are examples where you get rounding errors but for your use case this might be good enough
fun compute2(x: Number, y:Number) : Double{
return x.toDouble() + y.toDouble()
}

How do I need to write the 3rd line - Not enough information to infer type variable T

I'm new to Kotlin and try to convert a project from Java to Kotlin
I just need one last step and I don't understand what's going on :(
I'm getting a Not enough information to infer type variable T on model.predict call
override fun link(word: String): LinkSuggestion {
val input: DoubleArray = gramToInt.toArray(word)
val output: Array<Any> = model.predict(input)
// ~~~~~~~ Not enough information to infer type variable T
val maxPredictionIndex: Int = (output[output.size - 1] as Long).toInt()
val maxPredictionProbability: Double = output[maxPredictionIndex] as Double
return LinkSuggestion(word, intToLink.fromInt(maxPredictionIndex), maxPredictionProbability)
}
where model is import org.pmml4s.model.Model
The previous Java code:
#Override
public LinkSuggestion link(String word) {
double[] input = gramToInt.toArray(word);
Object[] output = model.predict(input);
int maxPredictionIndex = ((Long) output[output.length - 1]).intValue();
double maxPredictionProbability = (Double) output[maxPredictionIndex];
return new LinkSuggestion(word, intToLink.fromInt(maxPredictionIndex), maxPredictionProbability);
}
I needed to write
val output: Array<Any> = model.predict<Any>(input)

How to convert a Data Class to ByteBuffer in Kotlin?

I am trying to use Kinesis, which expects data in byte buffer format. All the examples I have seen so far are in Java and pass simple strings.
Can anybody give an idea of how to convert a kotlin data class to bytebuffer?
e.g.
data class abc (
var a: Long,
var b: String,
var c: Double
)
Check the below method
fun toByteArray(): ByteArray? {
val size: Int = 8 + 8 + string.Size
val byteBuffer = ByteBuffer.allocate(size)
.put(long) //long veriable
.put(double) // double veriable
.put(string)
return byteBuffer.array()
}
You can allocate the size based on dataType size like Int 4 bytes, Double and Long 8 bytes
for reading back to dataType
val byteBuffer = ByteBuffer.wrap(byteArray)
byteBuffer.get(Int) //Int variable
byteBuffer.get(Double) //Double variable
byteBuffer.get(nonce)
You might want to have a look at kotlinx.serialization. It is an official Kotlin project and supports several formats out-of-the-box. You can use the output and wrap it in with ByteBuffer.wrap
Thanks for all the suggestions.
Solved the problem using ObjectMapper() of Jackson library (jackson-databind) and annotations.
Following code used for serialization:
val objectMapper = ObjectMapper()
objectMapper.registerModule(JavaTimeModule())
val buf = ByteBuffer.wrap(objectMapper.writeValueAsString(className).toByteArray(Charsets.UTF_8))
code for deserialization:
val objectMapper = ObjectMapper()
objectMapper.registerModule(JavaTimeModule())
val obj = objectMapper.readValue(Charsets.UTF_8.decode(record.data()).toString(), ClassName::class.java)
Apart from this, I had to add constructors of all the data classes and had to add the following annotation to all the LocalDateTime attributes:
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
#JsonFormat(pattern = "YYYY-MM-dd HH:mm")
var edd: LocalDateTime?,
A simple solution with no additional libraries
Note: must be tailored for each data class
data class TimerConfig(val startTime: Long, val repeatCount: Int, val sequenceDuration: Int)
Converting the data class to a ByteArray
private fun TimerConfig.toByteArray(): ByteArray {
val byteBuffer = ByteBuffer.allocate(Long.SIZE_BYTES + Int.SIZE_BYTES + Int.SIZE_BYTES)
byteBuffer.putLong(this.startTime)
byteBuffer.putInt(this.repeatCount)
byteBuffer.putInt(this.sequenceDuration)
return byteBuffer.array()
}
Recovering the data class from the received ByteArray
private fun ByteArray.toTimerConfig(): TimerConfig {
val byteBuffer = ByteBuffer.wrap(this)
return TimerConfig(byteBuffer.long, byteBuffer.int, byteBuffer.int)
}

Idiomatic way to generate a random alphanumeric string in Kotlin

I can generate a random sequence of numbers in a certain range like the following:
fun ClosedRange<Int>.random() = Random().nextInt(endInclusive - start) + start
fun generateRandomNumberList(len: Int, low: Int = 0, high: Int = 255): List<Int> {
(0..len-1).map {
(low..high).random()
}.toList()
}
Then I'll have to extend List with:
fun List<Char>.random() = this[Random().nextInt(this.size)]
Then I can do:
fun generateRandomString(len: Int = 15): String{
val alphanumerics = CharArray(26) { it -> (it + 97).toChar() }.toSet()
.union(CharArray(9) { it -> (it + 48).toChar() }.toSet())
return (0..len-1).map {
alphanumerics.toList().random()
}.joinToString("")
}
But maybe there's a better way?
Since Kotlin 1.3 you can do this:
fun getRandomString(length: Int) : String {
val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
return (1..length)
.map { allowedChars.random() }
.joinToString("")
}
Lazy folks would just do
java.util.UUID.randomUUID().toString()
You can not restrict the character range here, but I guess it's fine in many situations anyway.
Assuming you have a specific set of source characters (source in this snippet), you could do this:
val source = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
java.util.Random().ints(outputStrLength, 0, source.length)
.asSequence()
.map(source::get)
.joinToString("")
Which gives strings like "LYANFGNPNI" for outputStrLength = 10.
The two important bits are
Random().ints(length, minValue, maxValue) which produces a stream of length random numbers each from minValue to maxValue-1, and
asSequence() which converts the not-massively-useful IntStream into a much-more-useful Sequence<Int>.
Using Collection.random() from Kotlin 1.3:
// Descriptive alphabet using three CharRange objects, concatenated
val alphabet: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
// Build list from 20 random samples from the alphabet,
// and convert it to a string using "" as element separator
val randomString: String = List(20) { alphabet.random() }.joinToString("")
Without JDK8:
fun ClosedRange<Char>.randomString(length: Int) =
(1..length)
.map { (Random().nextInt(endInclusive.toInt() - start.toInt()) + start.toInt()).toChar() }
.joinToString("")
usage:
('a'..'z').randomString(6)
To define it for a defined length:
val randomString = UUID.randomUUID().toString().substring(0,15)
where 15 is the number of characters
('A'..'z').map { it }.shuffled().subList(0, 4).joinToString("")
Using Kotlin 1.3:
This method uses an input of your desired string length desiredStrLength as an Integer and returns a random alphanumeric String of your desired string length.
fun randomAlphaNumericString(desiredStrLength: Int): String {
val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
return (1..desiredStrLength)
.map{ kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
}
If you prefer unknown length of alphanumeric (or at least a decently long string length like 36 in my example below), this method can be used:
fun randomAlphanumericString(): String {
val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
val outputStrLength = (1..36).shuffled().first()
return (1..outputStrLength)
.map{ kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
}
Or use coroutine API for the true Kotlin spirit:
buildSequence { val r = Random(); while(true) yield(r.nextInt(24)) }
.take(10)
.map{(it+ 65).toChar()}
.joinToString("")
Building off the answer from Paul Hicks, I wanted a custom string as input. In my case, upper and lower-case alphanumeric characters. Random().ints(...) also wasn't working for me, as it required an API level of 24 on Android to use it.
This is how I'm doing it with Kotlin's Random abstract class:
import kotlin.random.Random
object IdHelper {
private val ALPHA_NUMERIC = ('0'..'9') + ('A'..'Z') + ('a'..'z')
private const val LENGTH = 20
fun generateId(): String {
return List(LENGTH) { Random.nextInt(0, ALPHA_NUMERIC.size) }
.map { ALPHA_NUMERIC[it] }
.joinToString(separator = "")
}
}
The process and how this works is similar to a lot of the other answers already posted here:
Generate a list of numbers of length LENGTH that correspond to the index values of the source string, which in this case is ALPHA_NUMERIC
Map those numbers to the source string, converting each numeric index to the character value
Convert the resulting list of characters to a string, joining them with the empty string as the separator character.
Return the resulting string.
Usage is easy, just call it like a static function: IdHelper.generateId()
I use the following code to generate random words and sentences.
val alphabet: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
val randomWord: String = List((1..10).random()) { alphabet.random() }.joinToString("")
val randomSentence: String = (1..(1..10).random()).joinToString(" ") { List((1..10).random()) { alphabet.random() }.joinToString("") }
the question is old already, but I think another great solution (should work since Kotlin 1.3) would be the following:
// Just a simpler way to create a List of characters, as seen in other answers
// You can achieve the same effect by declaring it as a String "ABCDEFG...56789"
val alphanumeric = ('A'..'Z') + ('a'..'z') + ('0'..'9')
fun generateAlphanumericString(length: Int) : String {
// The buildString function will create a StringBuilder
return buildString {
// We will repeat length times and will append a random character each time
// This roughly matches how you would do it in plain Java
repeat(length) { append(alphanumeric.random()) }
}
}
fun randomAlphaNumericString(#IntRange(from = 1, to = 62) lenght: Int): String {
val alphaNumeric = ('a'..'z') + ('A'..'Z') + ('0'..'9')
return alphaNumeric.shuffled().take(lenght).joinToString("")
}
Building on Fabb111's answer:
fun randomString(length: Int): String =
buildString {
repeat(length) {
append((0 until 36).random().toString(36))
}
}
Numbers can be converted to a different base using the Int.toString(Int).
Base 36 is the numeral system that contains all alphanumeric characters
You can use RandomStringUtils.randomAlphanumeric(min: Int, max: Int) -> String from apache-commons-lang3
Here's a cryptographically secure version of it, or so I believe:
fun randomString(len: Int): String {
val random = SecureRandom()
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray()
return (1..len).map { chars[random.nextInt(chars.size)] }.joinToString("")
}
I used the most voted answer, but after using it for a while I discovered a big problem, since the random strings weren't that random.
I had to modify the generation of the random character, since if I only left allowedChars.random() it always generated the same strings, and I couldn't find why. I was reading that because random() was called very quickly, but I don't know how it works when calling it on the list of numbers.
fun getRandomString(): String {
val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
var string = ""
for (i in (1..20)) {
string += allowedChars[(Math.random() * (allowedChars.size - 1)).roundToInt()]
}
return string
}
// initialise at top
companion object {
private const val allowedCharacters = "0123456789QWERTYUIOPASDFGHJKLZXCVBNM"
}
//pass size and get Random String Captcha
fun getRandomCaptcha(sizeOfRandomCaptcha: Int): String {
val random = Random()
val sb = StringBuilder(sizeOfRandomCaptcha)
for (i in 0 until sizeOfRandomCaptcha)
sb.append(allowedCharacters[random.nextInt(allowedCharacters.length)])
return sb.toString()
}
Here's a simple function that uses newer Kotlin stdlib functions:
fun randomString(length: Int): String =
CharArray(length) { validChars.random() }.concatToString()
val validChars: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9'),
This uses:
a collection constructor with a initializer function
CharArray(length) { i -> /* provide a value for element i */ }
This is a one-liner for creating a CharArray and initializing each value using a lambda, It accepts a length, so the CharArray will be initialized with the correct size.
The Collection<>.random() extension function, that will pick a random character. This can be seeded if desired.
validChars.random()
The initialized CharArray is converted to a string using concatToString(), which was released in version 1.4.
The best way I think:
fun generateID(size: Int): String {
val source = "A1BCDEF4G0H8IJKLM7NOPQ3RST9UVWX52YZab1cd60ef2ghij3klmn49opq5rst6uvw7xyz8"
return (source).map { it }.shuffled().subList(0, size).joinToString("")
}

How to "prepend" a Char to a String in Kotlin

How in Kotlin can I prepend a Char to a String?
e.g.
fun main(args: Array<String>) {
val char = 'H'
val string = "ello World"
val appendingWorks = string + char //but not what I want...
//val prependingFails = char + string //no .plus(str:String) version
val prependingWorkaround1 = char.toString() + string
val prependingWorkaround2 = "" + char + string
val prependingWorkaround3 = String(charArray(char)) + string
}
When trying to call + (e.g. plus) on Char, there is no version that accepts a String on the right, so therefore 'H' + "ello World" doesn't compile
The first workaround might be good enough but it's a regression for me from what works in Java: String test = 'H' + "ello World"; (compiles fine...)
I also don't like the last workaround, at least in the java.lang.String I have a constructor that accepts a single char, or I can use java.lang.Character.toString(char c). Is there an elegant way in Kotlin to do so?
Was this discussed before (adding a plus(str:String) overload to the Char object?)
What about using string templates, like this:
val prepended = "$char$string"
As of kotlin 1.5, there is an extension plus operator function defined on Char, which can be used to concatenate a Char with given String. So you can do
val char = 'H'
val string = "ello World"
// Use the function call syntax
val result1 = char.plus(string)
// or use the operator syntax
val result2 = char + string
If you want to truly prepend a string using just a method call on that string, you can do the following:
val str = "ello World!"
println(str.let { 'H' + it })
This way can be useful if str was instead a large complicated chain of method calls:
val squares = ... // 10x10 array of square numbers
println(squares.joinToString("\n") {
it.joinToString(" ") { "%03d".format(it) }
}.let { "Squares:\n" + it })