|
1 | 1 | package strawman
|
2 | 2 | package collection
|
3 | 3 |
|
4 |
| -import scala.{AnyVal, Array, Char, Int, throws, Boolean, Serializable, Unit, `inline`, Option, Some, None, PartialFunction} |
| 4 | +import scala.{AnyVal, Array, Char, Int, throws, Boolean, Serializable, Unit, `inline`, Option, Some, None, PartialFunction, ArrayIndexOutOfBoundsException, NoSuchElementException, AnyRef} |
| 5 | +import scala.Predef.{implicitly, classOf} |
5 | 6 | import java.lang.String
|
6 | 7 | import mutable.ArrayBuilder
|
7 | 8 | import scala.reflect.ClassTag
|
8 |
| -import scala.math.{max, min} |
| 9 | +import scala.math.{max, min, Ordering} |
9 | 10 |
|
10 | 11 | object ArrayOps {
|
11 | 12 | /** A lazy filtered array. No filtering is applied until one of `foreach`, `map` or `flatMap` is called. */
|
@@ -69,6 +70,28 @@ object ArrayOps {
|
69 | 70 | /** Creates a new non-strict filter which combines this filter with the given predicate. */
|
70 | 71 | def withFilter(q: A => Boolean): WithFilter[A] = new WithFilter[A](a => p(a) && q(a), xs)
|
71 | 72 | }
|
| 73 | + |
| 74 | + private class ArrayIterator[A](private[this] val xs: Array[A]) extends Iterator[A] { |
| 75 | + private[this] var pos = 0 |
| 76 | + def hasNext: Boolean = pos < xs.length |
| 77 | + def next(): A = try { |
| 78 | + val r = xs(pos) |
| 79 | + pos += 1 |
| 80 | + r |
| 81 | + } catch { case _: ArrayIndexOutOfBoundsException => throw new NoSuchElementException } |
| 82 | + } |
| 83 | + |
| 84 | + private class GroupedIterator[A](xs: Array[A]) extends Iterator[Array[A]] { |
| 85 | + private[this] var pos = 0 |
| 86 | + def hasNext: Boolean = pos < xs.length |
| 87 | + def next(): Array[A] = { |
| 88 | + if(pos >= xs.length) throw new NoSuchElementException |
| 89 | + val r = xs.slice(pos, pos+size) |
| 90 | + pos += size |
| 91 | + r |
| 92 | + } |
| 93 | + } |
| 94 | + |
72 | 95 | }
|
73 | 96 |
|
74 | 97 | /** This class serves as a wrapper for `Array`s with many of the operations found in
|
@@ -179,6 +202,41 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
|
179 | 202 | /** The rest of the array without its `n` last elements. */
|
180 | 203 | def dropRight(n: Int): Array[A] = take(xs.length - max(n, 0))
|
181 | 204 |
|
| 205 | + /** Takes longest prefix of elements that satisfy a predicate. |
| 206 | + * |
| 207 | + * @param p The predicate used to test elements. |
| 208 | + * @return the longest prefix of this array whose elements all satisfy |
| 209 | + * the predicate `p`. |
| 210 | + */ |
| 211 | + def takeWhile(p: A => Boolean): Array[A] = { |
| 212 | + val i = indexWhere(x => !p(x)) |
| 213 | + val hi = if(i < 0) xs.length else i |
| 214 | + slice(0, hi) |
| 215 | + } |
| 216 | + |
| 217 | + /** Drops longest prefix of elements that satisfy a predicate. |
| 218 | + * |
| 219 | + * @param p The predicate used to test elements. |
| 220 | + * @return the longest suffix of this array whose first element |
| 221 | + * does not satisfy the predicate `p`. |
| 222 | + */ |
| 223 | + def dropWhile(p: A => Boolean): Array[A] = { |
| 224 | + val i = indexWhere(x => !p(x)) |
| 225 | + val lo = if(i < 0) xs.length else i |
| 226 | + slice(lo, xs.length) |
| 227 | + } |
| 228 | + |
| 229 | + def iterator(): Iterator[A] = new ArrayOps.ArrayIterator[A](xs) |
| 230 | + |
| 231 | + /** Partitions elements in fixed size arrays. |
| 232 | + * @see [[scala.collection.Iterator]], method `grouped` |
| 233 | + * |
| 234 | + * @param size the number of elements per group |
| 235 | + * @return An iterator producing arrays of size `size`, except the |
| 236 | + * last will be less than size `size` if the elements don't divide evenly. |
| 237 | + */ |
| 238 | + def grouped(size: Int): Iterator[Array[A]] = new ArrayOps.GroupedIterator[A](xs) |
| 239 | + |
182 | 240 | /** Splits this array into two at a given position.
|
183 | 241 | * Note: `c splitAt n` is equivalent to `(c take n, c drop n)`.
|
184 | 242 | *
|
@@ -228,6 +286,78 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
|
228 | 286 | res.result()
|
229 | 287 | }
|
230 | 288 |
|
| 289 | + /** Selects all elements of this array which do not satisfy a predicate. |
| 290 | + * |
| 291 | + * @param pred the predicate used to test elements. |
| 292 | + * @return a new array consisting of all elements of this array that do not satisfy the given predicate `pred`. |
| 293 | + */ |
| 294 | + def filterNot(p: A => Boolean): Array[A] = filter(x => !p(x)) |
| 295 | + |
| 296 | + /** Sorts this array according to an Ordering. |
| 297 | + * |
| 298 | + * The sort is stable. That is, elements that are equal (as determined by |
| 299 | + * `lt`) appear in the same order in the sorted sequence as in the original. |
| 300 | + * |
| 301 | + * @see [[scala.math.Ordering]] |
| 302 | + * |
| 303 | + * @param ord the ordering to be used to compare elements. |
| 304 | + * @return an array consisting of the elements of this array |
| 305 | + * sorted according to the ordering `ord`. |
| 306 | + */ |
| 307 | + def sorted[B >: A](implicit ord: Ordering[B]): Array[A] = { |
| 308 | + val len = xs.length |
| 309 | + if(xs.getClass.getComponentType.isPrimitive && len > 1) { |
| 310 | + // need to copy into a boxed representation to use Java's Arrays.sort |
| 311 | + val a = new Array[AnyRef](len) |
| 312 | + var i = 0 |
| 313 | + while(i < len) { |
| 314 | + a(i) = xs(i).asInstanceOf[AnyRef] |
| 315 | + i += 1 |
| 316 | + } |
| 317 | + java.util.Arrays.sort(a, ord.asInstanceOf[Ordering[AnyRef]]) |
| 318 | + val res = new Array[A](len) |
| 319 | + i = 0 |
| 320 | + while(i < len) { |
| 321 | + res(i) = a(i).asInstanceOf[A] |
| 322 | + i += 1 |
| 323 | + } |
| 324 | + res |
| 325 | + } else { |
| 326 | + val copy = slice(0, len) |
| 327 | + if(len > 1) |
| 328 | + java.util.Arrays.sort(copy.asInstanceOf[Array[AnyRef]], ord.asInstanceOf[Ordering[AnyRef]]) |
| 329 | + copy |
| 330 | + } |
| 331 | + } |
| 332 | + |
| 333 | + /** Sorts this array according to a comparison function. |
| 334 | + * |
| 335 | + * The sort is stable. That is, elements that are equal (as determined by |
| 336 | + * `lt`) appear in the same order in the sorted sequence as in the original. |
| 337 | + * |
| 338 | + * @param lt the comparison function which tests whether |
| 339 | + * its first argument precedes its second argument in |
| 340 | + * the desired ordering. |
| 341 | + * @return an array consisting of the elements of this array |
| 342 | + * sorted according to the comparison function `lt`. |
| 343 | + */ |
| 344 | + def sortWith(lt: (A, A) => Boolean): Array[A] = sorted(Ordering.fromLessThan(lt)) |
| 345 | + |
| 346 | + /** Sorts this array according to the Ordering which results from transforming |
| 347 | + * an implicitly given Ordering with a transformation function. |
| 348 | + * |
| 349 | + * @see [[scala.math.Ordering]] |
| 350 | + * @param f the transformation function mapping elements |
| 351 | + * to some other domain `B`. |
| 352 | + * @param ord the ordering assumed on domain `B`. |
| 353 | + * @tparam B the target type of the transformation `f`, and the type where |
| 354 | + * the ordering `ord` is defined. |
| 355 | + * @return an array consisting of the elements of this array |
| 356 | + * sorted according to the ordering where `x < y` if |
| 357 | + * `ord.lt(f(x), f(y))`. |
| 358 | + */ |
| 359 | + def sortBy[B](f: A => B)(implicit ord: Ordering[B]): Array[A] = sorted(ord on f) |
| 360 | + |
231 | 361 | /** Creates a non-strict filter of this array.
|
232 | 362 | *
|
233 | 363 | * Note: the difference between `c filter p` and `c withFilter p` is that
|
@@ -443,8 +573,8 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
|
443 | 573 | * @return a new array containing pairs consisting of corresponding elements of this array and `that`.
|
444 | 574 | * The length of the returned array is the minimum of the lengths of this array and `that`.
|
445 | 575 | */
|
446 |
| - def zip[B: ClassTag](that: Iterable[B]): Array[(A, B)] = { |
447 |
| - val b = new ArrayBuilder.ofRef[(A, B)] |
| 576 | + def zip[B](that: Iterable[B]): Array[(A, B)] = { |
| 577 | + val b = new ArrayBuilder.ofRef[(A, B)]()(ClassTag(classOf[(_, _)]).asInstanceOf[ClassTag[(A, B)]]) |
448 | 578 | val k = that.knownSize
|
449 | 579 | b.sizeHint(if(k >= 0) min(k, xs.length) else xs.length)
|
450 | 580 | var i = 0
|
@@ -589,7 +719,7 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal {
|
589 | 719 | val a3 = new Array[A3](xs.length)
|
590 | 720 | var i = 0
|
591 | 721 | while (i < xs.length) {
|
592 |
| - val e = xs(i) |
| 722 | + val e = xs(i).asInstanceOf[(A1, A2, A3)] |
593 | 723 | a1(i) = e._1
|
594 | 724 | a2(i) = e._2
|
595 | 725 | a3(i) = e._3
|
|
0 commit comments