Skip to content

Commit

Permalink
Implement ZipWith
Browse files Browse the repository at this point in the history
Implement ZipWith by defining a new method in `Iterator`, and a new case class for `View`.
Usage: `a.zipWith(b)(f)` is equivalent to `a.zip(b).map(t => f(t._1, t._2))` (but more efficient)
  • Loading branch information
Ethan Pronovost committed Sep 2, 2017
1 parent e790490 commit 24049b5
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
13 changes: 12 additions & 1 deletion src/main/scala/strawman/collection/Iterable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,18 @@ trait IterableOps[+A, +CC[X], +C] extends Any {
* `List("a", "b", "c").zipWithIndex == List(("a", 0), ("b", 1), ("c", 2))`
*/
def zipWithIndex: CC[(A @uncheckedVariance, Int)] = fromIterable(View.ZipWithIndex(toIterable))


/** Returns a $coll formed by zipping this $coll and another iterable collection,
* and applying `f` to each pair.
*
* Semantically equivalent to `this.zip(that).map(t => f(t._1, t._2))`
*
* @param that The other iterable to zip with
* @param f The function used to reduce each zipped pair
* @return A new collection
*/
def zipWith[B, R](that: Iterable[B])(f: (A, B) => R): CC[R] = fromIterable(View.ZipWith(toIterable, that, f))

/** Converts this $coll of pairs into two collections of the first and second
* half of each pair.
*
Expand Down
11 changes: 11 additions & 0 deletions src/main/scala/strawman/collection/Iterator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,17 @@ trait Iterator[+A] extends IterableOnce[A] { self =>
ret
}
}

/** Creates an iterator that zips each element produced by this iterator
* with one produced by the iterator of `that` and then applies `f` to each pair.
*
* @return a new iterator containing the output of `f` for each zipped pair
*/
def zipWith[B, R](that: IterableOnce[B])(f: (A, B) => R): Iterator[R] = new Iterator[R] {
val thatIterator = that.iterator()
def hasNext = self.hasNext && thatIterator.hasNext
def next() = f(self.next(), thatIterator.next())
}

def sameElements[B >: A](that: IterableOnce[B]): Boolean = {
val those = that.iterator()
Expand Down
11 changes: 10 additions & 1 deletion src/main/scala/strawman/collection/View.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,16 @@ object View extends IterableFactory[View] {
def iterator() = underlying.iterator().zip(other)
override def knownSize = underlying.knownSize min other.knownSize
}


/** A view that zips elements of the underlying collection with the elements
* of another collection or iterator, and then applies a function `f` to each pair.
*/
case class ZipWith[A, B, R](underlying: Iterable[A], other: Iterable[B], f: (A, B) => R) extends View[R] {
def iterator(): Iterator[R] = underlying.iterator().zipWith(other.iterator())(f)
override def knownSize: Int = underlying.knownSize min other.knownSize
}


/** A view that appends an element to its elements */
case class Append[A](underlying: Iterable[A], elem: A) extends View[A] {
def iterator(): Iterator[A] = Concat(underlying, View.Single(elem)).iterator()
Expand Down

0 comments on commit 24049b5

Please sign in to comment.