2010-01-25 74 views
11

我以編程和優雅的方式編寫特定的應用程序時遇到問題。我現在想這一段時間,但我不能找到一個「好」的解決了這個問題:在列表中迭代,返回當前,下一個和當前的元素

假設我有以下列表:

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,任何其他解決方案也非常感謝!

謝謝!

回答

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)) 

更新:繼承人,對工作流的一個版本。

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 
+0

我敢肯定,這有效,但我的斯卡拉版本似乎沒有滑動定義。我正在使用2.8.0.Beta1-RC7,哪個版本需要使用滑動? – Malax 2010-01-25 20:27:43

+0

我正在使用2.8.0.Beta1-RC8 – retronym 2010-01-25 20:32:15

+0

似乎RC8是必需的,現在就可以使用。謝謝! :-) – Malax 2010-01-25 20:42:09

3

Retronym的回答運作良好,如果你正在使用2.8。如果您使用的是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) 
+0

即使我已經使用Scala 2.8,這是一個非常好的學習代碼。感謝您的貢獻! – Malax 2010-01-25 20:37:54

2

更好地使用Scala的2.8和retronym'ssolution,當然,但這裏是我的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 
    } 
} 
相關問題