What's preferred to check if a string value is an ...
# getting-started
j
What's preferred to check if a string value is an integer? Or is there something better than these two?
Copy code
val myString = "1234"
val isNumeric = myString.toIntOrNull() != null
val isNumeric2 = myString.all { it.isDigit() }
h
Second one fails on negative integers... ⚠️
j
Thanks for the tips! Though I'm not worried about numbers being less than 1 or greater than Int.MAX_VALUE so I suppose these are both suitable.
e
"".all { it.isDigit() } == true
, and you probably shouldn't consider that an integer
"09"
has some varying interpretations
s
Copy code
fun String.isInteger(): Boolean {
    if(this.isEmpty()) return false
    val firstDigitIndex = if(this[0] == '-') {
        if(this.length==1) return false
        1
    } else 0
    if(this[firstDigitIndex]=='0') return false
    return this.substring(firstDigitIndex).all {it.isDigit()}
}
• disallows "", "-", "0...", "-0..." • doesn't check for Int.MAX/MIN_VALUE • should work as requested otherwise
Copy code
val isNumeric = myString.toIntOrNull() != null
looks suddenly very tempting, if and only if you want to make sure that this integer fits inside of an Int.
e
"0".isInteger() == false
doesn't look intended
s
good spot!
Copy code
fun String.isInteger(): Boolean = when {
    this.isEmpty() -> false
    this == "0" -> true
    this == "-0" -> true
    else -> {
        val firstDigitIndex = if(this[0] == '-') {
            if(this.length==1) return false
            1
        } else 0
        this[firstDigitIndex] != '0' && this.substring(firstDigitIndex).all { it.isDigit() }
    }
}
e
"-0"
is debatable but Java and Kotlin allow it 😛
s
added it a second before you sent your message 😄
e
in any case, I definitely agree that
.toIntOrNull() != null
is the most straightforward solution if you are looking for
Int
-sized integers
and for arbitrary sizes, regex DSL tends to be easier to reason about than a custom state machine like this
s
but only if you want to actually convert it to an Int.
otherwise longer sequences should be allowed
e
Copy code
"""-?(?:0|[1-9][0-9]*)""".toRegex()
s
regex is cheating 😂
or at least define the regex outside of the function, so that you don't reinitialise the Regex for every test.
for completeness, this would look like this:
Copy code
private val integerRegex = """-?(?:0|[1-9][0-9]*)""".toRegex()
fun String.isInteger(): Boolean = integerRegex.matches(this)