我需要使用 scala 打印字符串中相邻的重复字符及其计数。
例如: aaabbcda = 3a2b1c1d1a
我试过的是
object StringTransformation extends App {
val str = "aaabbcda"
strTransform(str)
def strTransform(str:String) {
var count = 1
for (i <- 1 until str.length) {
if(str.charAt(i-1) == str.charAt(i)){
count += 1
}else{
print(count+String.valueOf(str.charAt(i-1)))
count=1
}
}
print(count+str.takeRight(1))
}
}
尽管这是有效的,但这是程序化的,牢记命令式方法。有人可以建议使用 map() 或其他一些方法的功能方法。
最佳答案
函数式编程非常重视分解问题。在您的情况下,您的问题包括三个主要步骤
(1) 可以是它自己的函数,(2) 用
map
很容易做到,而 (3) 是一个简单的 println
在这一切的最后。(1) 将是最复杂的。我假设我们有一个
List
(在不同的 Scala 集合类型之间转换相对简单,列表非常适合练习递归)。// group() takes a list and a grouping function and returns the
// collection of adjacent elements, grouped by the function. In our
// case, the function will simply be the identity function, but we
// could also use it to define an equivalence class. For instance, if
// the function was toUpper or toLower, then our grouping would be
// case-insensitive.
def group[A, B](lst: List[A])(f: A => B): List[(B, Int)] = {
// This is our recursive helper function. It's defined in here
// because it's only useful in here. We keep track of the current
// element we're looking at and how many times we've seen it.
def go(curr: B, count: Int, xs: List[A]): List[(B, Int)] = {
// This is roughly your imperative solution, but written
// recursively and in more generality. We check if the next
// element is equal to our "current" element and branch
// accordingly.
xs match {
case Nil => List((curr, count))
case x :: xs =>
if (f(x) == curr) {
go(curr, count + 1, xs)
} else {
(curr, count) :: go(f(x), 1, xs)
}
}
}
// If the list starts out empty, there's no need to recurse. If the
// list is non-empty, then start at the beginning.
lst match {
case Nil => Nil
case x :: xs => go(f(x), 1, xs)
}
}
现在,要调用它,val str = "aaabbcda"
println(group(str.toList) { x => x }.map { case (b, n) => s"$n$b" }.mkString)
首先,我们使用 toList
将字符串转换为字符列表。 .一旦我们有了一个列表,我们就调用我们的 group()
具有用于比较键的标识函数的函数(因此一个字符只与自身比较)。后 group()
打电话,我们有List((Char, Int))
.然后我们打电话
map
在该列表中以您想要的方式将其格式化为字符串。这给了我们一个 List(String)
, 和 mkString
将这些字符串连接在一起。最后,我们println
字符串。此函数目前不是尾递归的。稍加努力,我们可能会使其成为尾递归,或者,如评论所示,尝试将我定义的递归函数转换为使用
foldLeft
的递归函数是一个很好的练习。 .但这是一个开始;我刚刚编写的所有代码都不依赖于可变性或传统的命令式循环结构。这是您在 Haskell 之类的语言中会看到的那种代码。
关于scala - 使用scala计算字符串中相邻的重复字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68084819/