I need to format a USA phone number, from the typi...
# random
c
I need to format a USA phone number, from the typical 10 digits to (123) 343-2345 I have this, but it feels a little cumbersome and not kotlin-y, but maybe it's what I have to do. Any suggestions?
Copy code
fun formatPhoneNumber(original: String): String {
    var number = original
    number =
        number.dropLast(4) +
            "-" +
            number.substring(
                number.length - 4,
                number.length,
            )
    number =
        number.substring(0, number.length - 8) +
            ")" +
            number.substring(
                number.length - 8,
                number.length,
            )
    (number.dropLast(12) +
            "(" +
            number.substring(
                    number.length - 12,
                    number.length,
            )).also { number = it }
    return number
}
r
Copy code
fun formatPhoneNumber(original: String) = buildString {
    append('(')
    append(original.substring(0, 3))
    append(") ")
    append(original.substring(3, 6))
    append('-')
    append(original.substring(6, 10))
}
c
<http://com.google.common.io|com.google.common.io>.Files.append
?
Oh. Just saw your edit. A couple of missing parens, but this is what I landed on.
Copy code
fun formatPhoneNumber(original: String) = buildString {
    append('(')
    append(original.substring(0, 3))
    append(") ")
    append(original.substring(3, 6))
    append('-')
    append(original.substring(6, 10))
}
This does look way better than the original. cheers
r
Yeah, sorry. I was typing from memory. I fixed it šŸ™‚
c
That's pretty good from memory!
šŸ˜† 3
m
Alternative using regex
Copy code
val numberGroups = """(\d{3})(\d{3})(\d{4})""".toRegex()

fun formatPhoneNumber(original: String) = original.replace(numberGroups, "($1) $2-$3")
ps: this message would have been better posted in #C1H43FDRB;)
today i learned 1
āž• 1
t
maybe overkilling, but I usually go with https://github.com/google/libphonenumber
c
Thanks. I will probably go for libphonenumber in the future.
m
yeah, I was about to suggest that lib. Used it in production years ago and does a great job.
k
As a long-time Java developer getting into Kotlin, can you tell me why
buildString
was chosen in the answer above instead of a simple string concatenation operator?
Copy code
fun formatPhoneNumber(original: String) =
    "(" + original.substring(0, 3) + ") " + original.substring(3, 6) + "-" + original.substring(6, 10)
Is there a performance-related reason or is it just more idiomatic?
āž• 1
m
Performance AND idiomaticism:
buildString()
gives you a DSL over a
StringBuilder
instance. Your code allocates 7 temporary strings before creating the final one. Of course its weight is negligible if ā€œoriginalā€ is short and the function isn’t executed in a hot loop or thousands time/sec. But anyway using that function, or a template string would be more idiomatic Kotlin.
k
Thanks, but is it really a performance gain to use
buildString
? In Java,
stringA + stringB + stringC
performs just as fast as using
StringBuilder
because the Java compiler generates the same bytecode, without creating any intermediate temporary string objects. It used to generate intermediate strings back in the days before Java 1.7. If Kotlin generates intermediate strings, doesn't this sound a little like a backward step?
m
Uh yes, my bad… I knew about the JDK 7 optimization, and that still applies if you use Kotlin/JVM. But keep in mind that Kotlin is a multi-platform language, so this couldn’t apply to other targets. As for using buildString() I guess it depends on the situation: the lambda will let you write additional construction logic while calling append() in a short way. As for me I always prefer string templates as the most idiomatic form, so I would have written that as
Copy code
"(${original.substring(0, 3)}) ${original.substring(3, 6)}-${original.substring(6, 10)}"
But in this case I prefer best my solution šŸ˜› https://kotlinlang.slack.com/archives/C09222272/p1628233961007000?thread_ts=1628180541.005400&amp;cid=C09222272
šŸ™ 1
t
since java 9 the replacement with string builder is replace indified string concatenation (https://openjdk.java.net/jeps/280). ofc this is all jit magic, so I am not exactly sure under which circumstances it happens, but one of the reason I like jvm is that you don’t care until you don’t care. as in, write the simplest code you can, don’t care about performance optimization (beyond the obvious one, don’t sort
O(n^2)
) until you don’t need to care. also why I am still not fully sold on multiplatform, but I really really need to try harder and more seriously