我在以scala-esque和优雅的方式编写特定应用程序时遇到问题。我现在尝试了一段时间,但是找不到这个问题的“好”解决方案:
鉴于我有以下列表:
List("foo", "bar", "baz", "blah")
我想迭代这个列表,不仅给出了每个迭代的当前元素,还给出了当前元素之前和之后的元素。这可能是一个Tuple3但不是必需的。这可能是元组签名:
(Option[T], T, Option[T])
为了澄清我的意思,这是List[String]
上每次迭代的拟议元组,在第四次之后结束。
迭代1:(None, "foo", Some("bar"))
迭代2:(Some("foo"), "bar", Some("baz"))
迭代3:(Some("bar"), "baz", Some("blah"))
迭代4:(Some("baz"), "blah", None)
我怎么能达到这样的结果?再说一遍:我不受Tuple3的约束,任何其他解决方案也非常感谢!
谢谢!
答案 0 :(得分:16)
这是一种方法。它使用新的Scala 2.8集合方法sliding
。
def window[A](l: List[A]): Iterator[List[Option[A]]] =
(None :: l.map(Some(_)) ::: List(None)) sliding 3
window(List(1, 2, 3, 4, 5)).toList
// List(List(None, Some(1), Some(2)), List(Some(1), Some(2), Some(3)), List(Some(2), Some(3), Some(4)), List(Some(3), Some(4), Some(5)), List(Some(4), Some(5), None))
更新:这是一个适用于Streams的版本。
def windowS[A](s: Stream[A]): Stream[List[Option[A]]] =
(None #:: s.map(Some(_): Option[A]) #::: Stream(None: Option[A])).sliding(3).toStream.map(_.toList)
val posInts = Stream.range(1, Integer.MAX_VALUE)
windowS(posInts).take(5).toList
答案 1 :(得分:3)
Retronym的答案会很好。如果您使用的是2.7.x,则没有出色的库存解决方案,但您可以轻松构建自己的解决方案。例如,如果您只想要存在之前和之后的三元组,您可以执行以下操作:
class Tuple3Iterator[T](solo: Iterator[T]) extends Iterator[(T,T,T)] {
var current = if (solo.hasNext) Some(solo.next) else None
var future = if (solo.hasNext) Some(solo.next) else None
def hasNext = solo.hasNext
def next = {
val past = current
current = future
future = Some(solo.next)
(past.get,current.get,future.get)
}
}
class IteratorToT3[T](it: Iterator[T]) {
def treble = new Tuple3Iterator[T](it)
}
implicit def allowTrebling[T](it: Iterable[T]) = new IteratorToT3[T](it.elements)
scala> List("Hi","there",5,"you").treble.foreach(println(_))
(Hi,there,5)
(there,5,you)
如果您希望在保留选项之前和之后允许,(编辑:我之前没有给出完整或无错误的更改集),请改为使用
class Tuple3Iterator[T](solo: Iterator[T]) extends Iterator[(Option[T],T,Option[T])] {
var current = None:Option[T]
var future = if (solo.hasNext) Some(solo.next) else None
def hasNext = (solo.hasNext || future!=None)
def next = {
val past = current
current = future
future = if (solo.hasNext) Some(solo.next) else None
(past,current.get,future)
}
}
scala> List("Hi","there",5,"you").treble.foreach(println(_))
(None,Hi,Some(there))
(Some(Hi),there,Some(5))
(Some(there),5,Some(you))
(Some(5),you,None)
答案 2 :(得分:2)
当然,最好使用Scala 2.8和retronym's solution,但这是我对Scala 2.7的解决方案:
class MyIterator[T](l: List[T]) extends Iterator[(Option[T],T,Option[T])] {
var last: Option[T] = None
var curr = l
def hasNext = !curr.isEmpty
def next = {
val t = curr match {
case first :: second :: tail => (last, first, Some(second))
case first :: Nil => (last, first, None)
case Nil => throw new java.util.NoSuchElementException
}
last = Some(curr.head)
curr = curr.tail
t
}
}