https://kotlinlang.org logo
Title
a

Adam S

03/12/2023, 9:59 AM
Is there is more succinct way to get the prefix of a string if and only if it ends with a suffix? Kotlin Playground
val names = listOf(
    "commonMain",
    "commonTest",
    "commonTestFixtures",
)

println(names.joinToString { getPrefix(it) })
// expected: common, common, common

fun getPrefix(name: String) =
    when {
        name.endsWith("Main") -> name.substringBeforeLast("Main")
        name.endsWith("Test") -> name.substringBeforeLast("Test")
        name.endsWith("TestFixtures") -> name.substringBeforeLast("TestFixtures")
        else -> error("invalid suffix")
    }
y

Youssef Shoaib [MOD]

03/12/2023, 10:05 AM
Playground:
val names = listOf(
    "commonMain",
    "commonTest",
    "commonTestFixtures",
    "jvmMain",
    "jvmTest",
    "jvmTestFixtures",
    "jsMain",
    "jsTest",
    "jsTestFixtures",
)

val suffixes = listOf("Main", "Test", "TestFixtures")

fun getPrefix(name: String) = 
    suffixes.find(name::endsWith)?.let(name::substringBeforeLast) ?: error("invalid suffix")


fun main() {
    println(names.joinToString { getPrefix(it) })
}
j

Joffrey

03/12/2023, 10:13 AM
There is
removeSuffix
which does exactly what you ask for, but chaining calls for different suffixes only works if you can guarantee that no item will have several suffixes in a row. E.g.
commonTestMain
would yield
common
, which might not be desirable.
n

nkiesel

03/14/2023, 3:16 AM
another (more complicated but potentially more efficient) solution:
val names = listOf(
    "commonMain",
    "commonTest",
    "commonTestFixtures",
    "jvmMain",
    "jvmTest",
    "jvmTestFixtures",
    "jsMain",
    "jsTest",
    "jsTestFixtures",
)

val suffixes = listOf("Main", "Test", "TestFixtures").joinToString("|", prefix="(.+)(", postfix=")") { """\Q$it\E""" }.toRegex()

fun getPrefix(name: String) = suffixes.matchEntire(name)?.groupValues?.get(1) ?: error("invalid suffix")

fun main() {
    println(names.joinToString { getPrefix(it) })
}
y

Youssef Shoaib [MOD]

03/14/2023, 1:33 PM
I don't think that solution would be more efficient for a small list of suffixes, due to the overhead of compiling regex. I think for like thousands of suffixes though sure it might perform better.
n

nkiesel

03/14/2023, 3:29 PM
Agreed
I like the earlier approach better. Regex starts to shine if the condition is not as simple as suffix/prefix