All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.collection.SortedMultiSet.scala Maven / Gradle / Ivy

The newest version!
package scala.collection

import scala.annotation.unchecked.uncheckedVariance

/**
  * Multiset whose elements are sorted
  * @tparam A Type of elements
  */
trait SortedMultiSet[A]
  extends MultiSet[A]
    with SortedMultiSetOps[A, SortedMultiSet, SortedMultiSet[A]] {

  def unsorted: MultiSet[A] = this

  def sortedIterableFactory: SortedIterableFactory[SortedMultiSet] = SortedMultiSet
  override protected def fromSpecific(coll: IterableOnce[A]): SortedMultiSet[A] = sortedIterableFactory.from(coll)(ordering)
  override protected def newSpecificBuilder: mutable.Builder[A, SortedMultiSet[A]] = sortedIterableFactory.newBuilder(ordering)
  override def empty: SortedMultiSet[A] = sortedIterableFactory.empty(ordering)
  override def withFilter(p: A => Boolean): SortedMultiSetOps.WithFilter[A, MultiSet, SortedMultiSet] = new SortedMultiSetOps.WithFilter(this, p)

}

trait SortedMultiSetOps[A, +CC[X] <: MultiSet[X], +C <: MultiSet[A]]
  extends MultiSetOps[A, MultiSet, C]
    with SortedOps[A, C] {

  def sortedIterableFactory: SortedIterableFactory[CC]

  protected def sortedFromIterable[B : Ordering](it: Iterable[B]): CC[B] = sortedIterableFactory.from(it)
  protected def sortedFromOccurrences[B : Ordering](it: Iterable[(B, Int)]): CC[B] =
    sortedFromIterable(it.view.flatMap { case (b, n) => new View.Fill(n)(b) })

  /** `this` sorted multiset upcasted to an unsorted multiset */
  def unsorted: MultiSet[A]

  def occurrences: SortedMap[A, Int]

  /**
    * Creates an iterator that contains all values from this collection
    * greater than or equal to `start` according to the ordering of
    * this collection. x.iteratorFrom(y) is equivalent to but will usually
    * be more efficient than x.from(y).iterator
    *
    * @param start The lower-bound (inclusive) of the iterator
    */
  def iteratorFrom(start: A): Iterator[A] =
    occurrences.iteratorFrom(start).flatMap { case (elem, n) => new View.Fill(n)(elem) }

  def firstKey: A = occurrences.firstKey
  def lastKey: A = occurrences.lastKey

  def rangeTo(to: A): C = {
    val i = rangeFrom(to).iterator
    if (i.isEmpty) return coll
    val next = i.next()
    if (ordering.compare(next, to) == 0)
      if (i.isEmpty) coll
      else rangeUntil(i.next())
    else
      rangeUntil(next)
  }

  /** Builds a new sorted multiset by applying a function to all elements of this sorted multiset.
    *
    *  @param f      the function to apply to each element.
    *  @tparam B     the element type of the returned collection.
    *  @return       a new collection resulting from applying the given function
    *                `f` to each element of this sorted multiset and collecting the results.
    */
  def map[B : Ordering](f: A => B): CC[B] = sortedFromIterable(new View.Map(toIterable, f))

  /**
    * Builds a new sorted multiset by applying a function to all pairs of element and its
    * number of occurrences.
    *
    * @param f  the function to apply
    * @tparam B the element type of the returned collection
    * @return   a new collection resulting from applying the given function
    *           `f` to each pair of element and its number of occurrences of this
    *           sorted multiset and collecting the results.
    */
  def mapOccurrences[B : Ordering](f: ((A, Int)) => (B, Int)): CC[B] =
    sortedFromOccurrences(new View.Map(occurrences, f))

  /**
    * Builds a new collection by applying a function to all elements of this sorted
    * multiset and using the elements of the resulting collections.
    *
    * @param f      the function to apply to each element.
    * @tparam B     the element type of the returned collection.
    * @return a new collection resulting from applying the given function `f` to
    *         each element of this sorted multiset and concatenating the results.
    */
  def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] = sortedFromIterable(new View.FlatMap(toIterable, f))

  /**
    * Builds a new collection by applying a function to all pairs of element and
    * its number of occurrences of this sorted multiset and using the elements of
    * the resulting collections.
    *
    * @param f      the function to apply to each element.
    * @tparam B     the element type of the returned collection.
    * @return a new collection resulting from applying the given function `f` to
    *         each pair of element and its number of occurrences of this sorted
    *         multiset and concatenating the results.
    */
  def flatMapOccurrences[B : Ordering](f: ((A, Int)) => IterableOnce[(B, Int)]): CC[B] =
    sortedFromOccurrences(new View.FlatMap(occurrences, f))

  /**
    * Returns a sorted multiset formed from this sorted multiset and another iterable
    * collection, by combining corresponding elements in pairs.
    * @param that The iterable providing the second half of each result pair
    * @param ev The ordering instance for type `B`
    * @tparam B the type of the second half of the returned pairs
    * @return a new sorted multiset containing pairs consisting of corresponding elements
    *         of this sorted multiset and `that`. The length of the returned collection
    *         is the minimum of the lengths of `this` and `that`
    */
  def zip[B](that: Iterable[B])(implicit ev: Ordering[B]): CC[(A @uncheckedVariance, B)] = // sound bcs of VarianceNote
    sortedFromIterable(new View.Zip(toIterable, that))(using Ordering.Tuple2(ordering, implicitly))

  /**
    * @return a new collection resulting from applying the given partial
    *         function `pf` to each element on which it is defined and
    *         collecting the results
    * @param pf the partial function which filters and map this sorted multiset
    * @tparam B the element type of the returned collection
    */
  def collect[B : Ordering](pf: PartialFunction[A, B]): CC[B] = flatMap(a =>
    if (pf.isDefinedAt(a)) new View.Single(pf(a))
    else View.Empty
  )

  /**
    * @return a new collection resulting from applying the given partial
    *         function `pf` to each group of occurrences on which it is defined and
    *         collecting the results
    * @param pf the partial function which filters and map this sorted multiset
    * @tparam B the element type of the returned collection
    */
  def collectOccurrences[B : Ordering](pf: PartialFunction[(A, Int), (B, Int)]): CC[B] = flatMapOccurrences(a =>
    if (pf.isDefinedAt(a)) new View.Single(pf(a))
    else View.Empty
  )

  // --- Override return type of methods that returned an unsorted MultiSet

  override def zipWithIndex: CC[(A, Int)] =
    sortedFromIterable(new View.ZipWithIndex(toIterable))(using Ordering.Tuple2(ordering, implicitly))

}

object SortedMultiSetOps {

  /** Specialize `WithFilter` for sorted collections
    *
    * @define coll sorted collection
    */
  class WithFilter[A, +IterableCC[_], +CC[X] <: MultiSet[X]](
    `this`: SortedMultiSetOps[A, CC, ?] & IterableOps[A, IterableCC, ?],
    p: A => Boolean
  ) extends IterableOps.WithFilter[A, IterableCC](`this`, p) {

    def map[B : Ordering](f: A => B): CC[B] =
      `this`.sortedIterableFactory.from(new View.Map(filtered, f))

    def flatMap[B : Ordering](f: A => IterableOnce[B]): CC[B] =
      `this`.sortedIterableFactory.from(new View.FlatMap(filtered, f))

    override def withFilter(q: A => Boolean): WithFilter[A, IterableCC, CC] =
      new WithFilter[A, IterableCC, CC](`this`, a => p(a) && q(a))

  }

}

object SortedMultiSet extends SortedIterableFactory.Delegate(immutable.SortedMultiSet)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy