将迭代器转换为重复块的迭代器 [英] Transforming an iterator into an iterator of chunks of duplicates

查看:69
本文介绍了将迭代器转换为重复块的迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我正在编写函数foo: Iterator[A] => Iterator[List[A]],将给定的迭代器转换为重复块的迭代器:

Suppose I am writing a function foo: Iterator[A] => Iterator[List[A]] to transform a given iterator into an iterator of chunks of duplicates :

def foo[T](it: Iterator[A]): Iterator[List[A]] = ???
foo("abbbcbbe".iterator).toList.map(_.mkString) // List("a", "bbb", "c", "bb", "e")

为了实现foo,我想重用函数splitDupes: Iterator[A] => (List[A], Iterator[A]),该函数将迭代器拆分为具有重复项和其余部分的前缀(非常感谢此处提出了建议)

In order to implement foo I want to reuse function splitDupes: Iterator[A] => (List[A], Iterator[A]) that splits an iterator into a prefix with duplicates and the rest (thanks a lot to Kolmar who suggested it here)

def splitDupes[A](it: Iterator[A]): (List[A], Iterator[A]) = {
  if (it.isEmpty) {
    (Nil, Iterator.empty)
  } else {
    val head = it.next
    val (dupes, rest) = it.span(_ == head)
    (head +: dupes.toList, rest)
  }
}

现在我正在使用splitDupes这样写foo:

Now I am writing foo using splitDupes like that:

def foo[A](it: Iterator[A]): Iterator[List[A]] = {
   if (it.isEmpty) {
     Iterator.empty
   } else {
     val (xs, ys) = Iterator.iterate(splitDupes(it))(x => splitDupes(x._2)).span(_._2.nonEmpty)
     (if (ys.hasNext) xs ++ Iterator(ys.next) else xs).map(_._1)
   }
}

此实现似乎可以正常工作,但看起来又复杂又笨拙.
您如何改善上述foo实施?

This implementation seems working but it's look complicated and clumsy.
How would you improve the foo implementation above ?

推荐答案

您可以这样做:

def foo[A](it: Iterator[A]): Iterator[List[A]] = {
  Iterator.iterate(splitDupes(it))(x => splitDupes(x._2))
    .map(_._1)
    .takeWhile(_.nonEmpty)
}

空案例已在splitDupes中处理.您可以放心地继续调用splitDupes,直到遇到空的情况为止(也就是说,开始在第一个元组元素中返回Nil).

The empty case is already handled in splitDupes. You can safely keep calling splitDupes until it hits this empty case (that is, starts returning Nil in the first tuple element).

在所有情况下都行得通:

This works ok in all cases:

scala> foo("abbbcbbe".iterator).toList.map(_.mkString)
res1: List[String] = List(a, bbb, c, bb, e)

scala> foo("".iterator).toList.map(_.mkString)
res2: List[String] = List()

scala> foo("a".iterator).toList.map(_.mkString)
res3: List[String] = List(a) 

scala> foo("aaa".iterator).toList.map(_.mkString)
res4: List[String] = List(aaa)

scala> foo("abc".iterator).toList.map(_.mkString)
res5: List[String] = List(a, b, c)

这篇关于将迭代器转换为重复块的迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆