https://kotlinlang.org logo
Title
s

Stephan Schroeder

10/09/2019, 2:48 PM
I don’t understand why
lastEndTokenIndex
is
-1
😐 If I use
lastIndexOf
without
fromIndex
than the result is the expected 40. But 40 is bigger than 0, so this fromIndex shouldn’t interfere with the result, should it??
fun main() {
    val sb = StringBuilder("<products><product>2</product><product>4</product></products>")
    val endToken = "</product>"
    val fromIndex = 0
    val lastEndTokenIndex = sb.lastIndexOf(endToken, fromIndex)
    println("lastEndTokenIndex: $lastEndTokenIndex")
}
Kotlin Playground: https://pl.kotl.in/SlHzdIq1j
k

karelpeeters

10/09/2019, 2:50 PM
It starts looking back from
fromIndex
.
s

Stephan Schroeder

10/09/2019, 2:55 PM
so how do I tell it that it can stop looking backwards, because it’s guaranteed not to be at the start of the string (because i already checked the start of the stringbuilder in an earlier iteration)?
k

karelpeeters

10/09/2019, 2:59 PM
I don't understand what you actually want to find. All indices? The first one? The last one?
s

Stephan Schroeder

10/09/2019, 3:00 PM
i’m looking for the last index that is bigger than fromIndex.
k

karelpeeters

10/09/2019, 3:00 PM
Then just do
lastIndexOf
and check if the result is indeed larger than
fromIndex
.
s

Stephan Schroeder

10/09/2019, 3:02 PM
yes, that works, but it’s inefficient, because in the real code the stringbuilder is created in a loop, so the start (everything before fromIndex) is already guaranteed to not contain endToken.
r

Ruckus

10/09/2019, 3:14 PM
Then write your own function
😁 1
s

Stephan Schroeder

10/09/2019, 3:24 PM
done 😎
fun StringBuilder.lastIndexOfAfter(str: String, startIndexOrAfter: Int): Int {
    tailrec fun lastIndexOfAfter(lastIndexFound: Int, sb: StringBuilder, str: String, fromIndex: Int): Int {
        val foundIndex = sb.indexOf(str, fromIndex)
        if(foundIndex==-1) {
            return lastIndexFound
        }else{
            return lastIndexOfAfter(foundIndex, sb, str, foundIndex+1)
        }
    }
    return lastIndexOfAfter(-1, this, str, startIndexOrAfter)
}
k

karelpeeters

10/09/2019, 3:24 PM
And can't you just look in the newly appended string instead?
Or what are you doing with the buffer?
s

Stephan Schroeder

10/09/2019, 3:25 PM
nope, because the string i’m looking for might have been created when the new chunk was appended (it was seperated before)
But my extension function seems to work and I even used
tailrec
in it, so I’m feeling pretty good right now 😎
in case somebody is interested in checking it out in the playground: https://pl.kotl.in/HMmaz6g3F
i guess this way less cooler implementation (no tailrec 😔) is superior in terms of readability and performance
fun StringBuilder.lastIndexOfAfter2(str: String, startIndexOrAfter: Int): Int {
    for(index in (this.length-str.length downTo startIndexOrAfter)) {
        if(this.startsWith(str, index)) {
            return index
        }
    }
    return -1
}
1