如何从Scala Iterable获取不同的项目,保持懒惰

Dan*_*ell 9 collections scala lazy-evaluation

我有一个java.lang.Iterable懒洋洋地计算其价值的东西.我从Scala访问它.是否存在仅返回不同值的核心API方式?例如,成像有一个过滤方法,也提供了迄今为止返回的所有结果:

val myLazyDistinctIterable = iterable.filter((previousReturnedItems, newItem) => previousReturnedItems.contains(newItem))
Run Code Online (Sandbox Code Playgroud)

我想这不是一般情况,因为它涉及存储以前返回的项目,这可能就是它不在核心API中的原因.

我知道List.distinctSets但是我想要的东西在被问到之前不会计算它的元素.

Tra*_*own 11

您可以使用该distinct方法Stream.例如,如果你有这个Iterable:

val it = new java.lang.Iterable[Int] {
  def iterator = new java.util.Iterator[Int] {
    var i = 0
    var first = true

    def hasNext = true
    def next =
      if (first) { first = false; i } else { first = true; i += 1; i - 1 }
    def remove() { throw new UnsupportedOperationException("Can't remove.") }
  }
}
Run Code Online (Sandbox Code Playgroud)

你可以写:

scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._

scala> val s = it.asScala.toStream
s: scala.collection.immutable.Stream[Int] = Stream(0, ?)

scala> s.take(10).toList
res0: List[Int] = List(0, 0, 1, 1, 2, 2, 3, 3, 4, 4)

scala> val s = it.asScala.toStream.distinct
s: scala.collection.immutable.Stream[Int] = Stream(0, ?)

scala> s.take(10).toList
res1: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
Run Code Online (Sandbox Code Playgroud)

我们可以告诉一切都是适当的懒惰,因为流是无限的.


gzm*_*zm0 6

更新仔细阅读问题很好.在这个解决方案中没有懒惰.抱歉.

toSet 会做你想要的:

  1. 将迭代元素存储在集合中(不是您想要的,但需要)
  2. 删除/替换重复项

val it = Seq(1,2,3,4,2,4): Iterable[Int]
it.toSet
// Set(1,2,3,4)
Run Code Online (Sandbox Code Playgroud)

如果你觉得很花哨,你可以将它转换回迭代:

it.toSet.toIterable
Run Code Online (Sandbox Code Playgroud)

或者,皮条客Iterable:

implicit class UniquableIterable[T](t: Iterable[T]) {
  def unique = t.toSet.toIterable
}
Run Code Online (Sandbox Code Playgroud)

然后打电话

it.unique
Run Code Online (Sandbox Code Playgroud)