parse string to an array in Kotlin - kotlin

How can I convert a string to an array of strings in Kotlin? To demonstrate, I have this:
val input_string = "[Hello, World]"
I would like to convert it to ["Hello", "World"].

Assuming that the array elements do not contain commas, you can do:
someString.removeSurrounding("[", "]")
.takeIf(String::isNotEmpty) // this handles the case of "[]"
?.split(", ")
?: emptyList() // in the case of "[]"
This will give you a List<String>. If you want an Array<String>:
someString.removeSurrounding("[", "]")
.takeIf(String::isNotEmpty)
?.split(", ")
?.toTypedArray()
?: emptyArray()

Assuming the strings only consist of letters and/or numbers you could also do it like this
val input_string = "[Hello, World]"
val list = Regex("\\w+").findAll(input_string).toList().map { it.value }

Related

Kotlin - add a single space between string and number

I have the following texts. I need to add a single space between the string and numbers.
Text1 -> Text 1
Text10 -> Text 10
Kotlin2 -> Kotlin 2
I used the following code, but it does not work.
fun addSpace(text: String): String {
return text.split("\\D".toRegex()).joinToString(separator = " ") { it }
}
It return only the number.
You can just replace any occurrence of a string of digits with a space followed by those digits:
fun addSpace(text: String) = text.replace(Regex("\\d+" ), " \$0")
(The $ is escaped so that the Kotlin compiler doesn't treat it as interpolation.)
You can use regex groups and replaceAll
fun main() {
val input = "Text1 Text10 Kotlin2"
val pattern = Pattern.compile("([a-zA-Z]+)([0-9]+)")
val matcher = pattern.matcher(input).replaceAll("$1 $2")
println(matcher)
}
Output will be
Text 1 Text 10 Kotlin 2

Obtain the length of the selected string in kotlin

I want to obtain the index chars or words in a string
for example
tv.text=" hey how are you, are you okay"
val res=tv.text.indexOf('h')
(have any way for put string instead of char?
output res=0
index of return only first char with h but in my tv text I have more h chars
can we return all h chars indexs
You can use filter function to get all the string indices with the required character.
val text = " hey how are you, are you okay"
val charToSearch = 'h'
val occurrences = text.indices.filter { text[it] == charToSearch }
println(occurences)
Try it yourself
And, if you want to search for strings instead of a single character, you can do this:
text.indices.filter { text.startsWith(stringToSearch, it) }
The following should work (you try to find an index if you found one in the previous iteration and you begin the folloing iteration from the previously found character instance plus 1, so that you don't find the same again and again):
fun main() {
val word = " hey how are you, are you okay"
val character = 'h'
var index: Int = word.indexOf(character)
while (index >= 0) {
println(index)
index = word.indexOf(character, index + 1)
}
}
If you want to store the indexes for later usage you can also do the following:
fun main() {
val word = " hey how are you, are you okay"
val character = 'h'
val indexes = mutableListOf<Int>()
var index: Int = word.indexOf(character)
while (index >= 0) {
index = word.indexOf(character, index + 1)
indexes.add(index)
}
println(indexes)
}
If you just want all the indices matching a char you can do this:
text.indices.filter { text[it] == 'h' }
Finding string matches is trickier, you could use Kotlin's regionMatches function to check if the part of the string starting at index matches what you're looking for:
val findMe = "you"
text.indices.filter { i ->
text.regionMatches(i, findMe, 0, findMe.length)
}
You could use a regular expression too, so long as you're careful about validating the search pattern:
Regex(findMe).findAll(text)
.map { it.range.first() } // getting the first index of each matching range
.toList()

Kotlin: check if string is numeric

Is there a simple way to check if user's input is numeric? Using regexes and exceptions seems too complicated here.
fun main {
val scan = Scanner(System.`in`)
val input = scanner.nextLine()
if (!input.isNumeric) {
println("You should enter a number!")
}
}
The method mentioned above will work for a number <= approximately 4*10^18 essentially max limit of Double.
Instead of doing that since String itself is a CharSequence, you can check if all the character belong to a specific range.
val integerChars = '0'..'9'
fun isNumber(input: String): Boolean {
var dotOccurred = 0
return input.all { it in integerChars || it == '.' && dotOccurred++ < 1 }
}
fun isInteger(input: String) = input.all { it in integerChars }
fun main() {
val input = readLine()!!
println("isNumber: ${isNumber(input)}")
println("isInteger: ${isInteger(input)}")
}
Examples:
100234
isNumber: true
isInteger: true
235.22
isNumber: true
isInteger: false
102948012120948129049012849102841209849018
isNumber: true
isInteger: true
a
isNumber: false
isInteger: false
Its efficient as well, there's no memory allocations and returns as soon as any non-satisfying condition is found.
You can also include check for negative numbers by just changing the logic if hyphen is first letter you can apply the condition for subSequence(1, length) skipping the first character.
joining all the useful comments and putting it in a input stream context, you can use this for example:
fun readLn() = readLine()!!
fun readNumericOnly() {
println("Enter a number")
readLn().toDoubleOrNull()?.let { userInputAsDouble ->
println("user input as a Double $userInputAsDouble")
println("user input as an Int ${userInputAsDouble.toInt()}")
} ?: print("Not a number")
}
readNumericOnly()
for input: 10
user input as a Double 10.0
user input as an Int 10
for input: 0.1
user input as a Double 0.1
user input as an Int 0
for input: "word"
Not a number
Simply use : text.isDigitsOnly() in kotlin.
Well all the answers here are best suited for their own scenarios:
But not all string are numeric digits it can have (-) and (.) decimal pointers.
So to accomplish this I made a cocktail of all the answers suggested below and from other posts as well which - looks like below :
fun isPosOrNegNumber(s: String?) : Boolean {
return if (s.isNullOrEmpty()) false
else{
if(s.first()=='-' && s.filter { it == '.' }.count() <= 1) {
s.removeRange(0,1).replace(".","").all{Character.isDigit(it)}
}
else s.all {Character.isDigit(it)}
}
}
Above code does a good job for its purpose.
But then it struck me kotlin does an even better job with matching a regex and voila the solution became simple and elegant as below :
fun isPosOrNegNumber(s: String?) : Boolean {
val regex = """^(-)?[0-9]{0,}((\.){1}[0-9]{1,}){0,1}$""".toRegex()
return if (s.isNullOrEmpty()) false
else regex.matches(s)
}
This sample regex is only for US number formats but if you want to use EU number formats then just replace '.' with ','
Bdw. if the numbers contain commas then just replace it while sending to this method or better form a regex pattern with commas in it.
Another way to check if the given string is numeric( to check for both negative and positive values ) or not:
val intChars = '0'..'9'
fun isNumeric(input: String) = input
.removePrefix("-")
.all { it in '0'..'9' }
A simple answer without any custom functions is to utilise toDoubleOrNull function. If it returns null, the string is not numeric.
val string = "-12345.666"
if (string.toDoubleOrNull()!=null) // string is numeric
{
//do something
}
If you know the input only contains integers you can also use toIntOrNull likewise

How can I create a map of the characters of a string and the number of their occurances in Kotlin?

I have a string "Hello World"
I need a Map<Char, Int> which will contain the pairs of each character and the number of times it appears in the string : {H=1, e=1, l=3, o=2,r=1, d=1}
How can I do that without using the traditional for loop?
Do it like this
val map = "Hello World".groupingBy { it }.eachCount()
map will be of type Map<Char, Int>

Checking if string is empty in Kotlin

In Java, we've always been reminded to use myString.isEmpty() to check whether a String is empty. In Kotlin however, I find that you can use either myString == "" or myString.isEmpty() or even myString.isBlank().
Are there any guidelines/recommendations on this? Or is it simply "anything that rocks your boat"?
Thanks in advance for feeding my curiosity. :D
Don't use myString == "", in java this would be myString.equals("") which also isn't recommended.
isBlank is not the same as isEmpty and it really depends on your use-case.
isBlank checks that a char sequence has a 0 length or that all indices are white space. isEmpty only checks that the char sequence length is 0.
/**
* Returns `true` if this string is empty or consists solely of whitespace characters.
*/
public fun CharSequence.isBlank(): Boolean = length == 0 || indices.all { this[it].isWhitespace() }
/**
* Returns `true` if this char sequence is empty (contains no characters).
*/
#kotlin.internal.InlineOnly
public inline fun CharSequence.isEmpty(): Boolean = length == 0
For String? (nullable String) datatype, I use .isNullOrBlank()
For String, I use .isBlank()
Why? Because most of the time, I do not want to allow Strings with whitespace (and .isBlank() checks whitespace as well as empty String). If you don't care about whitespace, use .isNullorEmpty() and .isEmpty() for String? and String, respectively.
Use isEmpty when you want to test that a String is exactly equal to the empty string "".
Use isBlank when you want to test that a String is empty or only consists of whitespace ("", " ").
Avoid using == "".
There are two methods available in Kotlin.
isNullOrBlank()
isNullOrEmpty()
And the difference is:
data = " " // this is a text with blank space
println(data.isNullOrBlank()?.toString()) //true
println(data.isNullOrEmpty()?.toString()) //false
You can use isNullOrBlank() to check is a string is null or empty. This method considers spaces only strings to be empty.
Here is a usage example:
val s: String? = null
println(s.isNullOrBlank())
val s1: String? = ""
println(s1.isNullOrBlank())
val s2: String? = " "
println(s2.isNullOrBlank())
val s3: String? = " a "
println(s3.isNullOrBlank())
The output of this snippet is:
true
true
true
false
As someone mentioned in the comments, you can use ifBlank, like so:
fun getSomeValue(): String {
// ...
val foo = someCall()
return foo.ifBlank { "some-default" }
}
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/if-blank.html