迭代列表,返回当前元素、下一个元素以及当前元素之前的元素

发布于 2024-08-18 17:56:02 字数 655 浏览 4 评论 0原文

我在以 scala 式且优雅的方式编写特定应用程序时遇到问题。我已经尝试了一段时间了,但我找不到解决此问题的“好的”解决方案:

鉴于我有以下列表:

List("foo", "bar", "baz", "blah")

我想迭代此列表,不仅为我提供每次迭代的当前元素,还为我提供当前元素之前和之后的元素。这可能是一个 Tuple3,但不是必需的。这可能是元组签名:

(Option[T], T, Option[T])

为了澄清我的意思,这是在 List[String] 上每次迭代的建议元组,在第四次之后结束。

迭代 1:(None, "foo", Some("bar"))

迭代 2:(Some("foo"),"bar",Some("baz"))< /code>

迭代 3: (Some("bar"), "baz", Some("blah"))

迭代 4: (Some("baz"), "blah",无)

我怎样才能达到这样的结果?再次强调:我不受 Tuple3 的约束,任何其他解决方案也非常感谢!

谢谢!

I have problems with writing an specific application in a scala-esque and elegant way. I tried this for some time now, but I cannot find a "good" solution to this Problem:

Given that I have the following List:

List("foo", "bar", "baz", "blah")

I want to Iterate over this list, not only giving me the current element for each Iteration but also the element before and after the current element. This might be a Tuple3 but is not required to. This could be the Tuple signature:

(Option[T], T, Option[T])

To clarify what i mean, this is the proposed Tuple for each iteration over a List[String], ending after the fourth.

Iteration 1: (None, "foo", Some("bar"))

Iteration 2: (Some("foo"), "bar", Some("baz"))

Iteration 3: (Some("bar"), "baz", Some("blah"))

Iteration 4: (Some("baz"), "blah", None)

How could I achieve such a result? Again: I am not bound to the Tuple3, any other solution is also very appreciated!

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

御守 2024-08-25 17:56:02

这是一种方法。它使用新的 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

Here's one approach. It uses a new Scala 2.8 collection method 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))

Update: Heres a version that works for 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
滥情稳全场 2024-08-25 17:56:02

如果您使用的是 2.8,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)

Retronym's answer works well if you're using 2.8. If you're using 2.7.x, there isn't a great stock solution, but you can build your own easily. For example, if you want only triples where before and after exist, you can do something like this:

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)

If you prefer to allow before and after to stay Options, (edit: I didn't really give a complete or error-free set of changes before) then instead use

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)
很快妥协 2024-08-25 17:56:02

更好地使用 Scala 2.8 和 retronym 解决方案,但这是我针对 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
  }
}

Better use Scala 2.8 and retronym's solution, of course, but here is my solution for 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
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文