This code snipped searches for the first regex match in a file for which one of the capture groups matches a local variable, and then obtains the value of the other capture group.
Is it possible to write this in an idiomatic, more efficient version which doesn't find all matches up front, but rather matches incrementally, without an explicit loop?
val id = ANCHOR_REGEX.findAll(apiFile.readText())
.find { label == it.groups["label"]?.value }
?.let { it.groups["id"]?.value }
CodePudding user response:
Yes, there is. And you've already done it. findAll
returns a Sequence<MatchResult>
, and just to be extra sure, we can look in the source code and see the implementation ourselves.
public actual fun findAll(input: CharSequence, startIndex: Int = 0): Sequence<MatchResult> {
if (startIndex < 0 || startIndex > input.length) {
throw IndexOutOfBoundsException("Start index out of bounds: $startIndex, input length: ${input.length}")
}
return generateSequence({ find(input, startIndex) }, MatchResult::next)
}
That's generateSequence
from the standard library, which produces lazy iterators whose next element is determined by calling the function repeatedly. find
on iterables is also perfectly capable of short-circuiting, so the code you've already written will incrementally find matches until it finds the one you want or exhausts the string.