```// 1 var c = 0 // count of number of times this...
# codingconventions
e
Copy code
// 1
var c = 0 // count of number of times this substitution is made in text
val newText = text.replace(re) {
    c += 1
    sub
}
or
Copy code
// 2
val c = re.findAll(text).asSequence().count()
val newText = text.replace(re, sub)
or something better?
c
if performance is a concern:
Copy code
val text = "abcdbdecbcd"
val matcher = "b".toPattern().matcher(text)
val sub = "Z"
var counter = 0
val newText = if(matcher.find()) {
	buildString(text.length) {
		do {
			counter++
			matcher.appendReplacement(this, sub)
		} while (matcher.find())
		matcher.appendTail(this)
	}
} else {
	text
}
// test:
check(counter == 3)
check(newText == "aZcdZdecZcd")
🤔 1
e
FYI, replacement string is guaranteed to be no longer than the original string
👌 1
I’m trying out the code in the KotlinPlayground. It made me replace
StringBuilder
with
StringBuffer
.
c
huh, that should not be necessary, in fact
StringBuilder
is better choice in this case.
e
Agreed. No concurrency.
c
By the way, if you use IntelliJ, Scratch files are awesome as a replacement for KotlinPlayground
e
I see that your code works but I don’t understand how the unchanged characters end up in the output string.
c
That's how matcher.appendReplacement is coded, take a look at its source if interested.
e
Got it. I’ll RTFM.
I’ve never seen a function like that when working with regexps. Thanks for pointing me to it.
c
in fact maybe I was wrong to think it'll have best performance, seems it creates an additional StringBuilder on each replacement.
1
e
I’d say that clarity and simplicity are more important to me than performance.
c
do you need
re
to be a regex, or is it just a normal substring replacement?
e
The
c += 1
in my original code (transliterated from JS) rubbed me the wrong way because functional programming, but there’s no need to pretend I’m in a purely functional language.
It’s a regex made by combining a bunch of individual strings into a regex (e.g.,
\\b(foo|bar|baz)\\b
).
c
you're performing an operation where you have two outputs - changed string and number of replacements, it is possible to do it without
counter++
, but won't be as readable
1
e
I don’t feel the need to be more efficient than the original JS code, but I do want it to look like it was written by a Kotlin programmer, not a JS programmer…
or a Scheme programmer.
😀 2
c
there are people who write very functional code in Kotlin, just look at the Arrow library
e
Yes, or I’d be duplicating the work, as shown in
2
.
I think I just need to get the middle ground between needlessly imperative and needlessly pure, while writing idiomatic Kotlin code. I greatly appreciate all of your help. I’m the only Kotlin programmer on my team, and just learned it in the fall, so this Slack has been very helpful.
I’ve been programming in Java since the 90s so have a lot to unlearn.
c
I've made a mistake, fixed now.
e
Where was the mistake?
c
there was no appendTail after the while loop
✔️ 1
I've thought about your requirements some more and it seems to me this would be a better version for you:
Copy code
val text = "abcdbdecbdz"
val matcher = "(b)".toPattern().matcher(text)
val sub = "Z"
val count = matcher.results().count()
val newText = matcher.replaceAll(sub)
it's much more readable and understandable than the loop and counter var version. The only drawback is that search is performed twice, as `replaceAll`resets the matcher state.
e
Very nice!
I have a Map where I need to look up each substitution, but your solution will generalize to that.
c
what do you mean? how does that map look?
e
Actually, never mind. I was thinking of a different part of my code.
I tried your code today but got
Unresolved reference: results
on the second-to-last line.
c
Oh, you're probably on Java 1.8 then, the
results()
was added in JDK9 I believe
1
e
Yeah, I’m using 1.8.
I’m on Android, which doesn’t support 1.9. 🤖
Thanks again for all of your help!
c
NP, glad I could help