Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get indexes of substrings contained in a string in Kotlin-way

Tags:

kotlin

I want to implement a function that will return the indexes of the substrings in the specified string. For now i did it in Java-style:

public fun String?.indexesOf(substr: String, ignoreCase: Boolean = true): List<Int> {
    var list = mutableListOf<Int>()
    if (substr.isNullOrBlank()) return list
    var count = 0;
    this?.split(substr, ignoreCase = ignoreCase)?.forEach {
        count += it.length
        list.add(count)
        count += substr.length
    }
    list.remove(list.get(list.size-1))
    return list
}

But I don't think this is a kotlin-way solution. Its most looks like typical java program but written in kotlin. How can this be implemented more elegantly using kotlin?

like image 373
RareScrap Avatar asked Nov 28 '22 21:11

RareScrap


2 Answers

what would i do is the following:

fun ignoreCaseOpt(ignoreCase: Boolean) = 
    if (ignoreCase) setOf(RegexOption.IGNORE_CASE) else emptySet()

fun String?.indexesOf(pat: String, ignoreCase: Boolean = true): List<Int> =
    pat.toRegex(ignoreCaseOpt(ignoreCase))
        .findAll(this?: "")
        .map { it.range.first }
        .toList()

// check:
println("xabcaBd".indexesOf("ab", true))
println("xabcaBd".indexesOf("ab", false))
println("xabcaBd".indexesOf("abx", true))

val s: String? = null
println(s.indexesOf("aaa"))

// output:
[1, 4]
[1]
[]
[]
like image 147
leetwinski Avatar answered Mar 25 '23 10:03

leetwinski


You could condense it down to something like this:

public fun String?.indexesOf(substr: String, ignoreCase: Boolean = true): List<Int> {
    return this?.let { 
        val regex = if (ignoreCase) Regex(substr, RegexOption.IGNORE_CASE) else Regex(substr)
        regex.findAll(this).map { it.range.start }.toList()
    } ?: emptyList()
}

Whether that's more efficient is a different matter. You'd have to test that.


If you wanted "aaa".indexesOf("aa") to return [0, 1] rather than just [0], you should be able to do that by modifying the regex to use positive lookahead, i.e.:

val regex = if (ignoreCase) Regex("(?=$substr)", RegexOption.IGNORE_CASE) else Regex("(?=$substr)")
like image 40
Michael Avatar answered Mar 25 '23 11:03

Michael