Reputation: 453
I have a program where I'm attempting to find the index of the nth occurrence of the letter "e". I guessed something like this...
def findE(line: String, ignore: Int) : Int = {
val pattern = "e".r
val index = line.indexOf(pattern(ignore+1))
index
}
where
ignore+1
is the desired group, but the syntax isn't valid. Was wondering if anyone knew how to go about this?
Upvotes: 1
Views: 300
Reputation: 1663
Here is my implementation that aims to provide a low-cost abstraction.
/** lazily finds all indices of a given char */
def indicesOf(s: String, of: Char): Iterator[Int] =
def from(idx: Int) = s.indexOf(of, idx + 1)
// we use an iterator because it is extremely light!
Iterator.iterate(from(-1))(from).takeWhile(_ >= 0)
//here is simple implementaiton of finding nth element
def indexOfNth(s: String, of:Char, n: Int) =
//`.slice(n, n+1).nextOption()` is needed due to lack of `.get(idx)` on iterator :(
indicesOf(s, of).slice(n, n+1).nextOption()
indexesOf
abstraction is usefull for other cases too://you can implement other tools based on indexesOf also
def dropLines(s: String, x: Int) = x match
case x if x <= 0 => s //we need to ensure that `Iterator#drop(x-1)` is stable
case other =>
indicesOf(s, '\n').drop(x - 1).nextOption() match
case Some(x) => s.drop(x + 1) // default case
case None => "" // case where we should drop more lines than exist in string
Upvotes: 0
Reputation: 6168
I'd use standard combinators if I were you.
> "abcdeabcdeabcde".zipWithIndex.collect {
case ('e', index) => index
}
res1: collection.immutable.IndexedSeq[Int] = Vector(4, 9, 14)
Just take whatever is at index 5, if it exists, and that's your answer.
Upvotes: 3