Skip to content

Commit 59438d0

Browse files
committed
SI-8835 Fix implementation of Iterator drop to remove quadratic behavior
1 parent 850899b commit 59438d0

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

src/library/scala/collection/Iterator.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,14 @@ trait Iterator[+A] extends TraversableOnce[A] {
320320
* it omits the first `n` values.
321321
* @note Reuse: $consumesAndProducesIterator
322322
*/
323-
def drop(n: Int): Iterator[A] = slice(n, Int.MaxValue)
323+
def drop(n: Int): Iterator[A] = {
324+
var j = 0
325+
while (j < n && this.hasNext) {
326+
this.next
327+
j += 1
328+
}
329+
this
330+
}
324331

325332
/** Creates an iterator returning an interval of the values produced by this iterator.
326333
*

test/files/run/iterators.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ test check_range2 was successful
44
test check_range3 was successful
55
test check_take was successful
66
test check_drop was successful
7+
test check_slice was successful
78
test check_foreach was successful
89
test check_forall was successful
910
test check_fromArray was successful

test/files/run/iterators.scala

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,42 @@ object Test {
5555
}
5656

5757
def check_drop: Int = {
58-
val it1 = Iterator.from(0)
59-
val it2 = it1 map { 2 * _ }
60-
val n1 = it1 drop 2 next
61-
val n2 = it2 drop 2 next;
62-
n1 + n2
58+
val tests = Array(
59+
Iterator.from(0).take(5).drop(1).toSeq sameElements Seq(1, 2, 3, 4),
60+
Iterator.from(0).take(5).drop(3).toSeq sameElements Seq(3, 4),
61+
62+
Iterator.from(0).take(5).drop(5).toSeq sameElements Seq(),
63+
Iterator.from(0).take(5).drop(10).toSeq sameElements Seq(),
64+
65+
Iterator.from(0).take(5).drop(0).toSeq sameElements Seq(0, 1, 2, 3, 4),
66+
Iterator.from(0).take(5).drop(-1).toSeq sameElements Seq(0, 1, 2, 3, 4),
67+
68+
Iterator.from(0).take(5).drop(1).map(2 * _).toSeq sameElements Seq(2, 4, 6, 8),
69+
Iterator.from(0).take(5).map(2 * _).drop(1).toSeq sameElements Seq(2, 4, 6, 8),
70+
71+
Iterator.from(0).take(5).drop(1).drop(2).toSeq sameElements Seq(3, 4),
72+
Iterator.from(0).take(5).drop(2).drop(1).toSeq sameElements Seq(3, 4)
73+
)
74+
tests.count(result => result)
75+
}
76+
77+
def check_slice: Int = {
78+
val tests = Array(
79+
Iterator.from(0).slice(3, 7).toSeq sameElements Seq(3, 4, 5, 6),
80+
Iterator.from(0).slice(3, 3).toSeq sameElements Seq(),
81+
Iterator.from(0).slice(-1, 3).toSeq sameElements Seq(0, 1, 2),
82+
Iterator.from(0).slice(3, -1).toSeq sameElements Seq(),
83+
84+
Iterator.from(0).slice(3, 7).map(2 * _).toSeq sameElements Seq(6, 8, 10, 12),
85+
Iterator.from(0).map(2 * _).slice(3, 7).toSeq sameElements Seq(6, 8, 10, 12),
86+
87+
Iterator.from(0).slice(3, 7).drop(1).toSeq sameElements Seq(4, 5, 6),
88+
Iterator.from(0).drop(1).slice(3, 7).toSeq sameElements Seq(4, 5, 6, 7),
89+
90+
Iterator.from(0).slice(3, 7).slice(1, 3).toSeq sameElements Seq(4, 5),
91+
Iterator.from(0).slice(3, 7).slice(1, 10).toSeq sameElements Seq(4, 5, 6)
92+
)
93+
tests.count(result => result)
6394
}
6495

6596
def check_foreach: Int = {
@@ -122,7 +153,8 @@ object Test {
122153
check_success("check_range2", check_range2, 26)
123154
check_success("check_range3", check_range3, 3)
124155
check_success("check_take", check_take, 10)
125-
check_success("check_drop", check_drop, 12)
156+
check_success("check_drop", check_drop, 10)
157+
check_success("check_slice", check_slice, 10)
126158
check_success("check_foreach", check_foreach, 190)
127159
check_success("check_forall", check_forall, 0)
128160
check_success("check_fromArray",check_fromArray, 14)

0 commit comments

Comments
 (0)