Skip to content

Commit c271074

Browse files
committed
Add sizeCompare, sizeIs and lengthIs
1 parent 2badce8 commit c271074

File tree

4 files changed

+131
-4
lines changed

4 files changed

+131
-4
lines changed

compat/src/main/scala-2.11/scala/collection/compat/package.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@
1313
package scala.collection
1414

1515
import scala.collection.generic.IsTraversableLike
16+
import scala.{collection => c}
1617

1718
package object compat extends compat.PackageShared {
1819
implicit def toTraversableLikeExtensionMethods[Repr](self: Repr)(
19-
implicit traversable: IsTraversableLike[Repr])
20-
: TraversableLikeExtensionMethods[traversable.A, Repr] =
20+
implicit traversable: IsTraversableLike[Repr])
21+
: TraversableLikeExtensionMethods[traversable.A, Repr] =
2122
new TraversableLikeExtensionMethods[traversable.A, Repr](traversable.conversion(self))
23+
24+
implicit def toSeqExtensionMethods[A](self: c.Seq[A]): SeqExtensionMethods[A] =
25+
new SeqExtensionMethods[A](self)
2226
}

compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,76 @@ class TraversableOnceExtensionMethods[A](private val self: c.TraversableOnce[A])
242242

243243
class TraversableExtensionMethods[A](private val self: c.Traversable[A]) extends AnyVal {
244244
def iterableFactory: GenericCompanion[Traversable] = self.companion
245+
246+
def sizeCompare(otherSize: Int): Int = SizeCompareImpl.sizeCompareInt(self)(otherSize)
247+
def sizeIs: SizeCompareOps = new SizeCompareOps(self)
248+
def sizeCompare(that: c.Traversable[_]): Int = SizeCompareImpl.sizeCompareColl(self)(that)
249+
}
250+
251+
class SeqExtensionMethods[A](private val self: c.Seq[A]) extends AnyVal {
252+
def lengthIs: SizeCompareOps = new SizeCompareOps(self)
253+
}
254+
255+
class SizeCompareOps private[compat] (private val it: c.Traversable[_]) extends AnyVal {
256+
import SizeCompareImpl._
257+
258+
/** Tests if the size of the collection is less than some value. */
259+
@inline def <(size: Int): Boolean = sizeCompareInt(it)(size) < 0
260+
261+
/** Tests if the size of the collection is less than or equal to some value. */
262+
@inline def <=(size: Int): Boolean = sizeCompareInt(it)(size) <= 0
263+
264+
/** Tests if the size of the collection is equal to some value. */
265+
@inline def ==(size: Int): Boolean = sizeCompareInt(it)(size) == 0
266+
267+
/** Tests if the size of the collection is not equal to some value. */
268+
@inline def !=(size: Int): Boolean = sizeCompareInt(it)(size) != 0
269+
270+
/** Tests if the size of the collection is greater than or equal to some value. */
271+
@inline def >=(size: Int): Boolean = sizeCompareInt(it)(size) >= 0
272+
273+
/** Tests if the size of the collection is greater than some value. */
274+
@inline def >(size: Int): Boolean = sizeCompareInt(it)(size) > 0
275+
}
276+
277+
private object SizeCompareImpl {
278+
def sizeCompareInt(self: c.Traversable[_])(otherSize: Int): Int =
279+
self match {
280+
case self: c.SeqLike[_, _] => self.lengthCompare(otherSize)
281+
case _ =>
282+
if (otherSize < 0) 1
283+
else {
284+
var i = 0
285+
val it = self.toIterator
286+
while (it.hasNext) {
287+
if (i == otherSize) return 1
288+
it.next()
289+
i += 1
290+
}
291+
i - otherSize
292+
}
293+
}
294+
295+
// `IndexedSeq` is the only thing that we can safely say has a known size
296+
def sizeCompareColl(self: c.Traversable[_])(that: c.Traversable[_]): Int =
297+
that match {
298+
case that: c.IndexedSeq[_] => sizeCompareInt(self)(that.length)
299+
case _ =>
300+
self match {
301+
case self: c.IndexedSeq[_] =>
302+
val res = sizeCompareInt(that)(self.length)
303+
// can't just invert the result, because `-Int.MinValue == Int.MinValue`
304+
if (res == Int.MinValue) 1 else -res
305+
case _ =>
306+
val thisIt = self.toIterator
307+
val thatIt = that.toIterator
308+
while (thisIt.hasNext && thatIt.hasNext) {
309+
thisIt.next()
310+
thatIt.next()
311+
}
312+
java.lang.Boolean.compare(thisIt.hasNext, thatIt.hasNext)
313+
}
314+
}
245315
}
246316

247317
class TraversableLikeExtensionMethods[A, Repr](private val self: c.GenTraversableLike[A, Repr])

compat/src/main/scala-2.12/scala/collection/compat/package.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
package scala.collection
1414

1515
import scala.collection.generic.IsTraversableLike
16+
import scala.{collection => c}
1617
import scala.collection.{mutable => m}
1718

1819
package object compat extends compat.PackageShared {
@@ -27,7 +28,10 @@ package object compat extends compat.PackageShared {
2728
}
2829

2930
implicit def toTraversableLikeExtensionMethods[Repr](self: Repr)(
30-
implicit traversable: IsTraversableLike[Repr])
31-
: TraversableLikeExtensionMethods[traversable.A, Repr] =
31+
implicit traversable: IsTraversableLike[Repr])
32+
: TraversableLikeExtensionMethods[traversable.A, Repr] =
3233
new TraversableLikeExtensionMethods[traversable.A, Repr](traversable.conversion(self))
34+
35+
implicit def toSeqExtensionMethods[A](self: c.Seq[A]): SeqExtensionMethods[A] =
36+
new SeqExtensionMethods[A](self)
3337
}

compat/src/test/scala/test/scala/collection/CollectionTest.scala

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,5 +109,54 @@ class CollectionTest {
109109
assertEquals(13, count)
110110
stream.force
111111
assertEquals(18, count)
112+
113+
@Test
114+
def sizeCompare(): Unit = {
115+
assertTrue(Set(1, 2, 3).sizeCompare(4) < 0)
116+
assertTrue(Set(1, 2, 3).sizeCompare(2) > 0)
117+
assertTrue(Set(1, 2, 3).sizeCompare(3) == 0)
118+
119+
assertTrue(List(1, 2, 3).sizeCompare(4) < 0)
120+
assertTrue(List(1, 2, 3).sizeCompare(2) > 0)
121+
assertTrue(List(1, 2, 3).sizeCompare(3) == 0)
122+
123+
assertTrue(Set(1, 2, 3).sizeCompare(List(1, 2, 3, 4)) < 0)
124+
assertTrue(Set(1, 2, 3).sizeCompare(List(1, 2)) > 0)
125+
assertTrue(Set(1, 2, 3).sizeCompare(List(1, 2, 3)) == 0)
126+
127+
assertTrue(Set(1, 2, 3).sizeCompare(Vector(1, 2, 3, 4)) < 0)
128+
assertTrue(Set(1, 2, 3).sizeCompare(Vector(1, 2)) > 0)
129+
assertTrue(Set(1, 2, 3).sizeCompare(Vector(1, 2, 3)) == 0)
130+
131+
assertTrue(Vector(1, 2, 3).sizeCompare(Set(1, 2, 3, 4)) < 0)
132+
assertTrue(Vector(1, 2, 3).sizeCompare(Set(1, 2)) > 0)
133+
assertTrue(Vector(1, 2, 3).sizeCompare(Set(1, 2, 3)) == 0)
134+
}
135+
136+
@Test
137+
def sizeIsLengthIs(): Unit = {
138+
assertTrue(Set(1, 2, 3).sizeIs < 4)
139+
assertTrue(Set(1, 2, 3).sizeIs <= 4)
140+
assertTrue(Set(1, 2, 3).sizeIs <= 3)
141+
assertTrue(Set(1, 2, 3).sizeIs == 3)
142+
assertTrue(Set(1, 2, 3).sizeIs >= 3)
143+
assertTrue(Set(1, 2, 3).sizeIs >= 2)
144+
assertTrue(Set(1, 2, 3).sizeIs > 2)
145+
146+
assertTrue(List(1, 2, 3).sizeIs < 4)
147+
assertTrue(List(1, 2, 3).sizeIs <= 4)
148+
assertTrue(List(1, 2, 3).sizeIs <= 3)
149+
assertTrue(List(1, 2, 3).sizeIs == 3)
150+
assertTrue(List(1, 2, 3).sizeIs >= 3)
151+
assertTrue(List(1, 2, 3).sizeIs >= 2)
152+
assertTrue(List(1, 2, 3).sizeIs > 2)
153+
154+
assertTrue(List(1, 2, 3).lengthIs < 4)
155+
assertTrue(List(1, 2, 3).lengthIs <= 4)
156+
assertTrue(List(1, 2, 3).lengthIs <= 3)
157+
assertTrue(List(1, 2, 3).lengthIs == 3)
158+
assertTrue(List(1, 2, 3).lengthIs >= 3)
159+
assertTrue(List(1, 2, 3).lengthIs >= 2)
160+
assertTrue(List(1, 2, 3).lengthIs > 2)
112161
}
113162
}

0 commit comments

Comments
 (0)