String 迭代器向文件中的重复行添加计数器

String 迭代器向文件中的重复行添加计数器,string,scala,iterator,String,Scala,Iterator,假设我正在编写一个函数Iterator[String]=>Iterator[String],将计数器附加到相邻的“重复”字符串,如下所示: def foo(it: Iterator[String]): Iterator[String] = ??? foo(Iterator("a", "a", "b", "a", "a", "a", "c", "a")) // ("a", "a1", "b", "a", "a1", "a2", "c", "a") 我正在编写一个函数来对所有相邻的重复项进行分组(

假设我正在编写一个函数
Iterator[String]=>Iterator[String]
,将计数器附加到相邻的“重复”字符串,如下所示:

def foo(it: Iterator[String]): Iterator[String] = ???
foo(Iterator("a", "a", "b", "a", "a", "a", "c", "a")) // ("a", "a1", "b", "a", "a1", "a2", "c", "a")
我正在编写一个函数来对所有相邻的重复项进行分组(如在运行长度编码中)
groupRepeated:Iterator[String]=>Iterator[List[String]]
,然后我可以简单地编写
foo

现在我想知道是否有更简单的解决办法。你有什么建议

另外,我更喜欢使用
TraversableOnce
的解决方案,而不是
Iterator

这个怎么样

def foo(it: Iterator[String]): Iterator[String] =
  new Iterator[String] {
    var currentElement: String = _
    var currentCount: Int = _

    override def hasNext: Boolean = it.hasNext

    override def next(): String = {
      val elem = it.next()

      if (elem == currentElement) {
        currentCount += 1

        s"${currentElement}${currentCount}"
      } else {
        currentElement = elem
        currentCount = 0

        elem
      }
    }
  }
其工作原理与预期一致:

foo(List("a", "a", "a", "b", "a", "a", "b", "b", "c").iterator).toList 
// res: List[String] = List("a", "a1", "a2", "b", "a", "a1", "b", "b1", "c") 

像这样的东西应该可以做到:

it.scanLeft (("", "", 0)) { 
 case ((pref, last, count), next) if next == pref => (pref, next + (count+1), count+1) 
 case (_, next) => (next, next, 0) 
}.drop(1)
 .map(_._2)

非常感谢。它很好,但“非功能性”,因为它使用可变状态。我想我的解决方案更“实用”。现在我想我更喜欢函数
TraversableOnce[String]=>TraversableOnce[String]
。我将更新这个问题。@Michael我将要说的主要是观点,但一般来说,在函数编程中,内部可变状态是可以的,因为对于调用方来说,函数仍然是纯的。另外,在任何情况下,如果你有一个迭代器,你已经有了一个可变引用。我同意迭代器首先是可变的。这就是为什么我认为
TraversableOnce
会更好。无论如何,你的解决方案可能比我的简单。谢谢你的努力@迈克尔:我修正了我的答案。对于泛型版本,您需要深入研究std库中的CanBuildFrom内容(它仍然是非常“可变的”)或者一些状态monad。