Skip to content

Instantly share code, notes, and snippets.

@tmbo
Created December 10, 2013 12:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmbo/7889544 to your computer and use it in GitHub Desktop.
Save tmbo/7889544 to your computer and use it in GitHub Desktop.
import scala.annotation.tailrec
import scala.App
object Test extends App {
val NumberOfRepetitions = 20
val longText = "This is a test text containing something and SoMETHING else." * 10000
println(s"Ready to start. Text size ${longText.length}")
val t = timeIt(longText.replaceAll("(?i)something", "someother"))
println(s"Time for regex: $t ms")
val t2 = timeIt(replaceAllCaseInsensitive(longText, "something", "someother"))
println(s"Time for custom: $t2 ms")
def timeIt[T](op: => T) = {
val t = System.currentTimeMillis
(1 to NumberOfRepetitions).foreach( _ => op)
(System.currentTimeMillis - t) / NumberOfRepetitions
}
def replaceAllCaseInsensitive(source: String, target: String, replacement: String) = {
val replacementSize = replacement.size
val sourceSize = source.size
val targetSize = target.size
val sizeDelta = replacementSize - targetSize
val builder = new StringBuilder(source)
val end = if(targetSize > 0) sourceSize - targetSize else sourceSize - 1
@inline
def findMatchAt(offset: Int): Boolean = {
var i = 0
while (i < targetSize) {
if (source.charAt(i + offset).toLower != target.charAt(i))
return false
i += 1
}
return true
}
@tailrec
def loop(currentIdx: Int = 0, offset: Int = 0): String = {
if (currentIdx <= end) {
if (findMatchAt(currentIdx)) {
builder.replace(currentIdx + offset, currentIdx + offset + targetSize, replacement)
loop(currentIdx + targetSize, offset + sizeDelta)
} else
loop(currentIdx + 1, offset)
} else {
builder.result()
}
}
loop()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment