zipWith (mapping over multiple Seq) in Scala

前端 未结 6 738
無奈伤痛
無奈伤痛 2020-12-05 06:38

Suppose I have

val foo : Seq[Double] = ...
val bar : Seq[Double] = ...

and I wish to produce a seq where the baz(i) = foo(i) + bar(i). One

6条回答
  •  清歌不尽
    2020-12-05 07:07

    When faced a similar task, I added the following pimp to Iterables:

    implicit class IterableOfIterablePimps[T](collOfColls: Iterable[Iterable[T]]) {
      def mapZipped[V](f: Iterable[T] => V): Iterable[V] = new Iterable[V] {
        override def iterator: Iterator[V] = new Iterator[V] {
          override def next(): V = {
            val v = f(itemsLeft.map(_.head))
            itemsLeft = itemsLeft.map(_.tail)
            v
          }
    
          override def hasNext: Boolean = itemsLeft.exists(_.nonEmpty)
    
          private var itemsLeft = collOfColls
        }
      }
    }
    

    Having this, one can do something like:

    val collOfColls = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
    collOfColls.mapZipped { group =>
      group // List(1, 4, 7), then List(2, 5, 8), then List(3, 6, 9)
    }
    

    Notice that you should carefully consider collection type passed as nested Iterable, since tail and head will be recurrently called on it. So, ideally you should pass Iterable[List] or other collection with fast tail and head.

    Also, this code expects nested collections of the same size. That was my use case, but I suspect this can be improved, if needed.

提交回复
热议问题