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?
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]
[]
[]
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)")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With