Is there a better way to check a string contains b...
# codereview
s
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
depends on what you want. note that (due to Char's 16-bit nature)
Copy code
"S".any { it.isLetter() } == true
"𐐠".any { it.isLetter() } == false
t
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
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
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
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
isn't there an
isLetterOrDigit()
in the JVM already?
m
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
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()
120 Views