Skip to content

Commit

Permalink
Merge pull request #3265 from kiendang/add-filternot
Browse files Browse the repository at this point in the history
Add `Stream.filterNot`
  • Loading branch information
mpilquist authored Jul 31, 2023
2 parents 62ba4a1 + 03ad1e3 commit af4d7c6
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
3 changes: 3 additions & 0 deletions core/shared/src/main/scala/fs2/Chunk.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ abstract class Chunk[+O] extends Serializable with ChunkPlatform[O] with ChunkRu
Chunk.array(b.result()).asInstanceOf[Chunk[O]]
}

/** Returns a chunk that has only the elements that do not satisfy the supplied predicate. */
def filterNot(p: O => Boolean): Chunk[O] = filter(!p(_))

/** Returns the first element for which the predicate returns true or `None` if no elements satisfy the predicate. */
def find(p: O => Boolean): Option[O] =
iterator.find(p)
Expand Down
4 changes: 4 additions & 0 deletions core/shared/src/main/scala/fs2/Stream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,10 @@ final class Stream[+F[_], +O] private[fs2] (private[fs2] val underlying: Pull[F,
*/
def filter(p: O => Boolean): Stream[F, O] = mapChunks(_.filter(p))

/** Emits only inputs which do not match the supplied predicate.
*/
def filterNot(p: O => Boolean): Stream[F, O] = mapChunks(_.filterNot(p))

/** Like `filter`, but allows filtering based on an effect.
*
* Note: The result Stream will consist of chunks that are empty or 1-element-long.
Expand Down
34 changes: 34 additions & 0 deletions core/shared/src/test/scala/fs2/StreamCombinatorsSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,40 @@ class StreamCombinatorsSuite extends Fs2Suite {
}
}

group("filterNot") {
property("1") {
forAll { (s: Stream[Pure, Int], n0: Int) =>
val n = (n0 % 20).abs + 1
val predicate = (i: Int) => i % n == 0
s.filterNot(predicate).assertEmits(s.toList.filterNot(predicate))
}
}

property("2") {
forAll { (s: Stream[Pure, Double]) =>
val predicate = (i: Double) => i - i.floor < 0.5
val s2 = s.mapChunks(c => Chunk.array(c.toArray))
assertEquals(s2.filterNot(predicate).toList, s2.toList.filterNot(predicate))
}
}

property("3") {
forAll { (s: Stream[Pure, Byte]) =>
val predicate = (b: Byte) => b < 0
val s2 = s.mapChunks(c => Chunk.array(c.toArray))
s2.filterNot(predicate).assertEmits(s2.toList.filterNot(predicate))
}
}

property("4") {
forAll { (s: Stream[Pure, Boolean]) =>
val predicate = (b: Boolean) => !b
val s2 = s.mapChunks(c => Chunk.array(c.toArray))
s2.filterNot(predicate).assertEmits(s2.toList.filterNot(predicate))
}
}
}

property("find") {
forAll { (s: Stream[Pure, Int], i: Int) =>
val predicate = (item: Int) => item < i
Expand Down

0 comments on commit af4d7c6

Please sign in to comment.