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。