https://kotlinlang.org logo
#codereview
Title
# codereview
s

Simon Lin

09/10/2021, 8:43 AM
Is there a better way to check a string contains both number and alphabet?
Copy code
val text = "aas211w"
if (text.any { it.isDigit() } && text.any { it.isLetter() }) {
}
e

ephemient

09/10/2021, 8:56 AM
depends on what you want. note that (due to Char's 16-bit nature)
Copy code
"ï¼³".any { it.isLetter() } == true
"𐐠".any { it.isLetter() } == false
t

Tobias Suchalla

09/10/2021, 10:21 AM
any
also only checks if at least one of the chars matches the predicate, I suspect you might want
all
:
Copy code
val text = "aas211w"
if (text.all { it.isDigit() || it.isLetter() }) {
    // do something
}
m

Matteo Mirk

09/10/2021, 12:58 PM
Copy code
val text = """aas211W𐐠S""" // contains UTF8 letters
text.matches("""[\p{L}\d]+""".toRegex()) // true, UTF8-inclusive
if you just need to match ASCII letters the regex becomes
"""[a-zA-Z\d]+"""
k

Klitos Kyriacou

09/10/2021, 1:42 PM
I was wondering what you meant by "contains UTF8 letters". A String doesn't normally contain UTF8, that's just an encoding scheme for converting bytes into characters code points. I presume you meant your source code contained UTF8 letters, but once parsed and stored in a String they are just Unicode letters.
m

Matteo Mirk

09/10/2021, 2:34 PM
Sorry, my mistake, I confused terms: I meant unicode letters outside of the ASCII range. I used the wrong word, the encoding in place of the code points.
b

brandonmcansh

09/11/2021, 6:10 PM
isn't there an
isLetterOrDigit()
in the JVM already?
m

Matteo Mirk

09/13/2021, 1:53 PM
there is an extension method in Kotlin SDK since 1.0:
fun Char.isLetterOrDigit(): Boolean
an yes, there are the static methods in the Char class •
public static boolean isLetterOrDigit(char ch)
since Java 1 •
public static boolean isLetterOrDigit(int codePoint)
since Java 5 good catch Brandon, I totally forgot those!
e

ephemient

09/14/2021, 5:49 PM
back to the original question… if the desire is to do something like those vexing password rules (must have a digit, must have a letter) then
.isLetterOrDigit()
doesn't help, but the original can be modified to be Unicode-safe on JVM:
Copy code
"aas211w".codePoints()
    .map { if (Character.isDigit(it)) 1 else if (Character.isletter(it)) 2 else 0 }
    .reduce(0, Int::or) == 3
🙌 1
or if Java 8+ isn't available, something like
generateSequence(0) { offsetByCodePoints(it, 1) }.takeWhile { it < length }.map { codePointAt(it) }
instead of
.codePoints()
54 Views