Skip to content

Instantly share code, notes, and snippets.

@yongjhih
Last active January 9, 2023 13:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yongjhih/79c6def38793378fd11e07bc5130ea3e to your computer and use it in GitHub Desktop.
Save yongjhih/79c6def38793378fd11e07bc5130ea3e to your computer and use it in GitHub Desktop.
fun CharSequence.replacePatternsSorted(patterns: Iterable<String>, onReplace: (CharSequence) -> CharSequence): CharSequence =
replacePatterns(patterns.sortedByDescending { it.length }, onReplace)
fun CharSequence.replacePatterns(patterns: Iterable<Regex>, onReplace: (CharSequence) -> CharSequence): CharSequence {
val patternsIterator = patterns.iterator()
if (!patternsIterator.hasNext()) return this
val matches = patternsIterator.next().findAll(this)
val nextPatterns = patternsIterator.asSequence().toList()
if (!matches.iterator().hasNext()) return replacePatterns(nextPatterns, onReplace)
return ranges(matches.map { it.range }.asIterable())
.map { if (it.first) onReplace(it.second) else it.second.replacePatterns(nextPatterns, onReplace) }
.joinToString("")
}
fun CharSequence.ranges(sortedRanges: Iterable<IntRange>): Sequence<Pair<Boolean, CharSequence>> =
range.ranges(sortedRanges).map { it.first to substring(it.second) }
fun IntRange.ranges(sortedRanges: Iterable<IntRange>): Sequence<Pair<Boolean, IntRange>> = sequence {
var left = first
for (range in sortedRanges) {
val newRange = left until range.first
if (!newRange.isEmpty()) yield(false to newRange)
yield(true to range)
left = range.last + 1
if (left > last) break
}
val newRange = left..last
if (!newRange.isEmpty()) yield(false to newRange)
}
```
assertThat(
"#abcd #abcd".replacePatterns(listOf("#abcd ", "#abc")) { "{$it}" }
).isEqualTo("{#abcd }{#abc}d")
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment