Reputation: 447
Let's say I have the string:
"AAAAA BBB CCCC AA"
I want a way that I can count the occurrences of consecutive characters to give a string that looks like:
"5A 3B 4C 2A"
How do I go about this?
Currently, I have tried looping through the string, and for each character, I use a match case, and within each case, I start a new loop to count how many times that character appears consecutively, I then try to replace that substring with the desired substring.
Upvotes: 0
Views: 1008
Reputation: 22850
For this kind of problems, I like to write my own tail-recursive algorithm.
def countConsecutiveCharacters(str: String): List[(Char, Int)] = {
@annotation.tailrec
def loop(remaining: List[Char], currentChar: Char, currentCount: Int,
acc: List[(Char, Int)]): List[(Char, Int)] =
remaining match {
case char :: xs if(char == currentChar) =>
loop(
remaining = xs,
currentChar,
currentCount + 1,
acc
)
case char :: xs =>
loop(
remaining = xs,
currentChar = char,
currentCount = 1,
(currentChar -> currentCount) :: acc
)
case Nil =>
((currentChar -> currentCount) :: acc).reverse
}
str.toList match {
case char :: list =>
loop(
remaining = list,
currentChar = char,
currentCount = 1,
acc = List.empty
)
case Nil =>
List.empty
}
}
You can checkout the code working here.
You may replace all that with one foldLeft
, but IMHO, this way is cleaner and easier to read.
Upvotes: 1
Reputation: 51271
Build a List
of (n:Int, c:Char)
tuples then reformat it to whatever String
representation you desire.
"AAAAABBBCCCCAA".foldRight(List.empty[(Int,Char)]){
case (c, hd::tl) if c == hd._2 => (hd._1 + 1, c) :: tl
case (c, lst) => (1,c) :: lst
}.map(tup => s"${tup._1}${tup._2}").mkString(" ")
//res0: String = 5A 3B 4C 2A
Upvotes: 4