在迭代器列表上对此flatMap进行Lazify

时间:2013-11-20 22:37:55

标签: scala lazy-evaluation

鉴于此功能,我无法修改:

def numbers(c: Char): Iterator[Int] = 
  if(Character.isDigit(c)) Iterator(Integer.parseInt(c.toString)) 
  else Iterator.empty
// numbers: (c: Char)Iterator[Int]

这个输入数据:

val data = List('a','b','c','1','d','&','*','x','9')
// data: List[Char] = List(a, b, c, 1, d, &, *, x, 9)

如何使这个函数变得懒惰,以便data仅处理到第一个出现的数字字符?

def firstNumber(data: List[Char]) :Int = data.flatMap(numbers).take(1)

4 个答案:

答案 0 :(得分:6)

data.iterator.flatMap(numbers).take(1).toList

不要使用溪流;您不需要存储旧数据。不要使用观点;他们没有得到精心维护,无论如何都是矫枉过正的。

如果您需要Int,则需要一些默认行为。根据具体情况,您可以选择

data.iterator.flatMap(numbers).take(1).headOption.getOrElse(0)

或类似

{
  val ns = data.iterator.flatMap(numbers)
  if (ns.hasNext) ns.next
  else throw new NoSuchElementException("Number missing")
}

答案 1 :(得分:2)

只需在数据上调用.toStream即可:

firstNumber(data.toStream)

答案 2 :(得分:2)

一种可能性是使用Scala的集合视图: http://www.scala-lang.org/docu/files/collections-api/collections_42.html

在集合上调用.view可以让您在集合上调用mapflatMap等函数,而不会生成中间结果。

所以在你的情况下你可以写:

data.view.flatMap(numbers).take(1).force

这会为List[Int]提供最多一个元素,并且仅将data处理到第一个数字。

答案 3 :(得分:-1)

你可以使用Streams:

http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Stream

流创建的一种方式:

1 #:: 2 #:: empty