How to "prepend" a Char to a String in Kotlin - 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 })

Related

Count the number of punctuation symbols in a string Kotlin

I have a question how can I count the number of punctuation symbols in a string.
Here is my code snippet
fun punctuationCount(stringValue: Editable): Int {
val trimmedStr = stringValue.trim()
return if (trimmedStr.isEmpty()) {
0
} else {
return trimmedStr.split("[a-zA-Z&&[ \t]]".toRegex()).size
}
}
You can make use of the built-in count function on CharSequence to count the occurrence of arbitrary characters.
val testString = "Some string containing punctuation, like !, #, #, etc."
val punctuationChars = setOf('!', '#', '#', '$', '%', '.')
val occurrences = testString.count { char -> char in punctuationChars }
println("I've counted $occurrences occurrences!")
If you need this functionality more often, you might want to extract it into an extension function, e.g.
fun CharSequence.countCharacters(searchedCharacters: Set<Char>): Int =
this.count { char -> char in searchedCharacters }
val punctuationChars = setOf('!', '#', '#', '$', '%', '.')
fun CharSequence.countPunctuationCharacters(): Int =
this.countCharacters(punctuationChars)
Then you can do
val occurrences = testString.countPunctuationCharacters()
Thanks to #CryptoFool for the example string.
Here's a version of your function that demonstrates what you're asking for:
fun punctuationCount(stringValue: String): Long {
val trimmedStr = stringValue.trim()
return if (trimmedStr.isEmpty()) {
return 0
} else {
val exp = Pattern.compile("\\p{Punct}")
val matcher = exp.matcher(trimmedStr)
return matcher.results().count()
}
}
If you don't like the Pattern library's definition of what constitutes punctuation, you can replace the line that computes the Pattern object with something like this that lets you define punctuation characters explicitly:
val exp = Pattern.compile("[!##\$%.]")
Another variation - the Unicode standard defines a bunch of categories (see 4.4) that a character can fall into, and those are present in Kotlin, so you could make use of those if you like
import kotlin.text.CharCategory.*
val punctuation = setOf(
DASH_PUNCTUATION, START_PUNCTUATION, END_PUNCTUATION,
CONNECTOR_PUNCTUATION, OTHER_PUNCTUATION
)
val testString = "Some string containing punctuation, like !, #, #, etc."
fun main() {
testString.count { it.category in punctuation }.run(::println)
}
>>> 8
You'd have to decide if those cover your needs, or which ones to include and exclude (and symbols are a different category class). Just throwing it out there as an option / something to know about!

Kotlin spread operator behaviour on chars array

I have been using Kotlin for some time now, but I just found out that when I would like to use spread operator on the array of chars and pass it to the split function, it does not work.
fun main() {
val strings = arrayOf("one", "two")
val stringSplit = "".split("one", "two")
val stringsSplit = "".split(*strings)
val chars = arrayOf('1', '2')
val charSplit = "".split('1', '2')
val charsSplit = "".split(*chars) // this is not possible
}
produces following error (same during the build and same in the official try kotlin repl)
Am I doing something wrong?
This happens because in Kotlin Array<Char> is equal to Character[] in Java, not to char[] in Java.
To use the spread operator on an array of characters and pass it to a vararg Char parameter, you need to use CharArray which is equal to char[] in Java.
fun main() {
val strings = arrayOf("one", "two")
val stringSplit = "".split("one", "two")
val stringsSplit = "".split(*strings)
val chars = charArrayOf('1', '2')
val charSplit = "".split('1', '2')
val charsSplit = "".split(*chars) // this is not possible
}

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 convert string to char in Kotlin?

fun main(args: Array<String>) {
val StringCharacter = "A"
val CharCharacter = StringCharacter.toChar()
println(CharCharacter)
}
I am unable to convert string A to char.
I know that StringCharacter = 'A' makes it char but I need the conversion.
Thanks.
A CharSequence (e.g. String) can be empty, have a single character, or have more than one character.
If you want a function that "returns the single character, or throws an exception if the char sequence is empty or has more than one character" then you want single:
val string = "A"
val char = string.single()
println(char)
And if you want to call single by a different name you can create your own extension function to do so:
fun CharSequence.toChar() = single()
Usage:
val string = "A"
val char = string.toChar()
println(char)
You cannot convert a String to a Char, because a String is an array of Chars. Instead, select a Char from the String:
val string = "A"
val character = string.get(0) // Or string[0]
println(character)
A String cannot be converted to a Char because String is an array of chars. You can convert a String to an Char array or you can get a character from that String.
Example:
val a = "Hello"
val ch1 = a.toCharArray()[0] // output: H
val ch2 = a[0] // output: H

Kotlin JS - string to number conversion?

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.