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

izumi.fundamentals.collections.nonempty.NEMap.scala Maven / Gradle / Ivy

The newest version!
package izumi.fundamentals.collections.nonempty

// shameless copypaste from Scalactic

import scala.collection.{Iterable, Seq, mutable}
import scala.collection.mutable.{ArrayBuffer, Buffer}
import scala.reflect.ClassTag
import scala.collection.compat.*
import scala.language.implicitConversions

// Can't be a LinearSeq[T] because Builder would be able to create an empty one.
/**
  * A non-empty map: an ordered, immutable, non-empty collection of key-value tuples with LinearSeq performance characteristics.
  *
  * 

* The purpose of NEMap is to allow you to express in a type that a Map is non-empty, thereby eliminating the * need for (and potential exception from) a run-time check for non-emptiness. For a non-empty sequence with IndexedSeq * performance, see Vector. *

* *

Constructing NEMaps

* *

* You can construct a NEMap by passing one or more elements to the NEMap.apply factory method: *

* *
  * scala> NEMap(1 -> "one", 2 -> "two", 3 -> "three")
  * res0: org.scalactic.anyvals.NEMap[Int, String] = NEMap(1 -> "one", 2 -> "two", 3 -> "three")
  * 
* *

Working with NEMaps

* *

* NEMap does not extend Scala's Map or Traversable traits because these require that * implementations may be empty. For example, if you invoke tail on a Seq that contains just one element, * you'll get an empty Seq: *

* *
  * scala> Map(1 -> "one").tail
  * res6: Map[Int] = Map()
  * 
* *

* On the other hand, many useful methods exist on Map that when invoked on a non-empty Seq are guaranteed * to not result in an empty Map. For convenience, NEMap defines a method corresponding to every such Map * method. Here are an example: *

* *
  * NEMap(1 -> "one", 2 -> "two", 3 -> "three").map(t => (t._1 + 1, t._2))                        // Result: NEMap(2 -> "one", 3 -> "two", 4 -> "three")
  * 
* *

* NEMap does not currently define any methods corresponding to Map methods that could result in * an empty Map. However, an implicit converison from NEMap to Map * is defined in the NEMap companion object that will be applied if you attempt to call one of the missing methods. As a * result, you can invoke filter on an NEMap, even though filter could result * in an empty map—but the result type will be Map instead of NEMap: *

* *
  * NEMap(1 -> "one", 2 -> "two", 3 -> "three").filter(_._1 < 10) // Result: Map(1 -> "one", 2 -> "two", 3 -> "three")
  * NEMap(1 -> "one", 2 -> "two", 3 -> "three").filter(_._ 1> 10) // Result: Map()
  * 
* *

* You can use NEMaps in for expressions. The result will be an NEMap unless * you use a filter (an if clause). Because filters are desugared to invocations of filter, the * result type will switch to a Map at that point. Here are some examples: *

* *
  * scala> import org.scalactic.anyvals._
  * import org.scalactic.anyvals._
  *
  * scala> for ((i, j) <- NEMap(1 -> "one", 2 -> "two", 3 -> "three")) yield (i + 1, j)
  * res0: org.scalactic.anyvals.NEMap[Int, String] = NEMap(2 -> "one", 3 -> "two", 4 -> "three")
  *
  * scala> for ((i, j) <- NEMap(1, 2, 3) if i < 10) yield (i + 1, j)
  * res1: Map[Int, String] = Map(2 -> "one", 3 -> "two", 4 -> "three")
  * 
* * @tparam K the type of key contained in this NEMap * @tparam V the type of value contained in this NEMap */ final class NEMap[K, +V] private (val toMap: Map[K, V]) extends AnyVal { def keySet: NESet[K] = NESet.unsafeFrom(toMap.keySet) /** * Returns a new NEMap containing the entries of this NEMap and the entries of the passed NEMap. * The entry type of the resulting NEMap is the most specific superclass encompassing the entry types of this and the passed NEMap. * * @tparam V1 the value type of the returned NEMap * @param other the NEMap to append * @return a new NEMap that contains all the elements of this NEMap and all elements of other. */ def ++[V1 >: V](other: NEMap[K, V1]): NEMap[K, V1] = new NEMap(toMap ++ other.toMap) /** * Returns a new NEMap containing the entries of this NEMap and the entries of the passed Vector. * The entry type of the resulting NEMap is the most specific superclass encompassing the entry types of this NEMap and the passed Vector. * * @tparam V1 the value type of the returned NEMap * @param other the Vector to append * @return a new NEMap that contains all the entries of this NEMap and all elements of other. */ def ++[V1 >: V](other: Vector[(K, V1)]): NEMap[K, V1] = new NEMap(toMap ++ other.toVector) // TODO: Have I added these extra ++, etc. methods to Vector that take a NEMap? /** * Returns a new NEMap containing the entries of this NEMap and the entries of the passed TraversableOnce. * The entry type of the resulting NEMap is the most specific superclass encompassing the entry types of this NEMap * and the passed TraversableOnce. * * @tparam V1 the value type of the returned NEMap * @param other the TraversableOnce to append * @return a new NEMap that contains all the elements of this NEMap followed by all elements of other. */ def ++[V1 >: V](other: IterableOnce[(K, V1)]): NEMap[K, V1] = if (other.iterator.isEmpty) this else new NEMap(toMap ++ other.iterator.toMap) /** * Returns a new NEMap with the given entry added. * *

* Note that :-ending operators are right associative. A mnemonic for +: vs. :+ is: the COLon goes on the COLlection side. *

* * @param entry the element to add to this NEMap * @return a new NEMap consisting of element followed by all elements of this NEMap. */ def +:[V1 >: V](entry: (K, V1)): NEMap[K, V1] = new NEMap(toMap + entry) /** * As with ++, returns a new NEMap containing the entries of this NEMap and the entries of the passed NEMap. * The entry type of the resulting NEMap is the most specific superclass encompassing the entry types of this and the passed NEMap. * * It differs from ++ in that the right operand determines the type of the resulting collection rather than the left one. Mnemonic: the COLon is on the side of the new COLlection type. * * @tparam V1 the value type of the returned NEMap * @param other the NEMap to add * @return a new NEMap that contains all the elements of this NEMap and all elements of other. */ def ++:[V1 >: V](other: NEMap[K, V1]): NEMap[K, V1] = new NEMap(toMap ++ other.toMap) /** * As with ++, returns a new NEMap containing the entries of this NEMap and the entries of the passed Vector. * The entry type of the resulting NEMap is the most specific superclass encompassing the entry types of this NEMap and the passed Vector. * * It differs from ++ in that the right operand determines the type of the resulting collection rather than the left one. Mnemonic: the COLon is on the side of the new COLlection type. * * @tparam V1 the value type of the returned NEMap * @param other the Vector to append * @return a new NEMap that contains all the entries of this NEMap and all elements of other. */ def ++:[V1 >: V](other: Vector[(K, V1)]): NEMap[K, V1] = new NEMap(toMap ++ other.toVector) /** * Returns a new NEMap containing the entries of this NEMap and the entries of the passed TraversableOnce. * The entry type of the resulting NEMap is the most specific superclass encompassing the entry types of this NEMap * and the passed TraversableOnce. * * @tparam V1 the value type of the returned NEMap * @param other the TraversableOnce to append * @return a new NEMap that contains all the elements of this NEMap followed by all elements of other. */ def ++:[V1 >: V](other: IterableOnce[(K, V1)]): NEMap[K, V1] = if (other.iterator.isEmpty) this else new NEMap(toMap ++ other.iterator.toMap) /** * Returns a new NEMap with the given entry added. * * @param entry the entry to add to this NEMap * @return a new NEMap consisting of all entries of this NEMap and entry. */ def +[V1 >: V](entry: (K, V1)): NEMap[K, V1] = new NEMap(toMap + entry) /** * Returns a new NEMap with the given entries added. * * @param entries the entries to add to this NEMap * @return a new NEMap consisting of all entries of this NEMap and entries. */ def +[V1 >: V](entries: (K, V1)*): NEMap[K, V1] = new NEMap(toMap ++ entries) /** * Appends all entries of this NEMap to a string builder. The written text will consist of a concatenation of the result of invoking toString * on of every entry of this NEMap, without any separator string. * * @param sb the string builder to which entries will be appended * @return the string builder, sb, to which entries were appended. */ def addString(sb: StringBuilder): StringBuilder = toMap.addString(sb) /** * Appends all entries of this NEMap to a string builder using a separator string. The written text will consist of a concatenation of the * result of invoking toString * on of every element of this NEMap, separated by the string sep. * * @param sb the string builder to which entries will be appended * @param sep the separator string * @return the string builder, sb, to which elements were appended. */ def addString(sb: StringBuilder, sep: String): StringBuilder = toMap.addString(sb, sep) /** * Appends all entries of this NEMap to a string builder using start, end, and separator strings. The written text will consist of a concatenation of * the string start; the result of invoking toString on all elements of this NEMap, * separated by the string sep; and the string end * * @param sb the string builder to which elements will be appended * @param start the starting string * @param sep the separator string * @param start the ending string * @return the string builder, sb, to which elements were appended. */ def addString(sb: StringBuilder, start: String, sep: String, end: String): StringBuilder = toMap.addString(sb, start, sep, end) /** * Selects an value by its key in the NEMap. * * @return the value of this NEMap at key k. */ def apply(k: K): V = toMap(k) /** * Finds the first entry of this NEMap for which the given partial function is defined, if any, and applies the partial function to it. * * @param pf the partial function * @return an Option containing pf applied to the first entry for which it is defined, or None if * the partial function was not defined for any entry. */ def collectFirst[U](pf: PartialFunction[(K, V), U]): Option[U] = toMap.collectFirst(pf) /** * Indicates whether this NEMap contains a binding for given key. * * @param key the key to look for * @return true if this NEMap has a binding that is equal (as determined by ==) to key, false otherwise. */ infix def contains(key: K): Boolean = toMap.contains(key) /** * Copies entries of this NEMap to an array. Fills the given array arr with entries of this NEMap. Copying * will stop once either the end of the current NEMap is reached, or the end of the array is reached. * * @param arr the array to fill */ def copyToArray[V1 >: V](arr: Array[(K, V1)]): Unit = { toMap.copyToArray(arr) () } /** * Copies entries of this NEMap to an array. Fills the given array arr with entries of this NEMap, beginning at * index start. Copying will stop once either the end of the current NEMap is reached, or the end of the array is reached. * * @param arr the array to fill * @param start the starting index */ def copyToArray[V1 >: V](arr: Array[(K, V1)], start: Int): Unit = { toMap.copyToArray(arr, start) () } /** * Copies entries of this NEMap to an array. Fills the given array arr with at most len entries of this NEMap, beginning at * index start. Copying will stop once either the end of the current NEMap is reached, the end of the array is reached, or * len elements have been copied. * * @param arr the array to fill * @param start the starting index * @param len the maximum number of elements to copy */ def copyToArray[V1 >: V](arr: Array[(K, V1)], start: Int, len: Int): Unit = { toMap.copyToArray(arr, start, len) () } /** * Copies all elements of this NEMap to a buffer. * * @param buf the buffer to which elements are copied */ def copyToBuffer[V1 >: V](buf: Buffer[(K, V1)]): Unit = { buf ++= toMap () } /** * Counts the number of elements in this NEMap that satisfy a predicate. * * @param p the predicate used to test elements. * @return the number of elements satisfying the predicate p. */ def count(p: ((K, V)) => Boolean): Int = toMap.count(p) /* override def equals(o: Any): Boolean = o match { case NEMap: NEMap[?] => toMap == NEMap.toMap case _ => false } */ /** * Indicates whether a predicate holds for at least one of the entries of this NEMap. * * @param p the predicate used to test entries. * @return true if the given predicate p holds for some of the entries of this NEMap, otherwise false. */ def exists(p: ((K, V)) => Boolean): Boolean = toMap.exists(p) /** * Finds the first entry of this NEMap that satisfies the given predicate, if any. * * @param p the predicate used to test elements * @return an Some containing the first element in this NEMap that satisfies p, or None if none exists. */ def find(p: ((K, V)) => Boolean): Option[(K, V)] = toMap.find(p) /** * Builds a new NEMap by applying a function to all entries of this NEMap and using the entries of the resulting NEMaps. * * @tparam K1 the key type of the returned NEMap * @tparam V1 the value type of the returned NEMap * @param f the function to apply to each entry. * @return a new NEMap containing entries obtained by applying the given function f to each entry of this NEMap and concatenating * the entries of resulting NEMaps. */ def flatMap[K1, V1](f: ((K, V)) => NEMap[K1, V1]): NEMap[K1, V1] = { val buf = new ArrayBuffer[(K1, V1)] for (ele <- toMap) buf ++= f(ele).toMap new NEMap(buf.toMap) } /** * Folds the entries of this NEMap using the specified associative binary operator. * *

* The order in which operations are performed on entries is unspecified and may be nondeterministic. *

* * @tparam U a type parameter for the binary operator, a supertype of (K, V). * @param z a neutral element for the fold operation; may be added to the result an arbitrary number of * times, and must not change the result (e.g., Nil for list concatenation, * 0 for addition, or 1 for multiplication.) * @param op a binary operator that must be associative * @return the result of applying fold operator op between all the elements and z */ def fold[U >: (K, V)](z: U)(op: (U, U) => U): U = toMap.fold(z)(op) /** * Applies a binary operator to a start value and all elements of this NEMap, going left to right. * * @tparam B the result type of the binary operator. * @param z the start value. * @param op the binary operator. * @return the result of inserting op between consecutive entries of this NEMap, going left to right, with the start value, * z, on the left: * *
    * op(...op(op(z, x_1), x_2), ..., x_n)
    * 
* *

* where x1, ..., xn are the elements of this NEMap. *

*/ def foldLeft[B](z: B)(op: (B, (K, V)) => B): B = toMap.foldLeft(z)(op) /** * Applies a binary operator to all entries of this NEMap and a start value, going right to left. * * @tparam B the result of the binary operator * @param z the start value * @param op the binary operator * @return the result of inserting op between consecutive entries of this NEMap, going right to left, with the start value, * z, on the right: * *
    * op(x_1, op(x_2, ... op(x_n, z)...))
    * 
* *

* where x1, ..., xn are the elements of this NEMap. *

*/ def foldRight[B](z: B)(op: ((K, V), B) => B): B = toMap.foldRight(z)(op) /** * Indicates whether a predicate holds for all entries of this NEMap. * * @param p the predicate used to test entries. * @return true if the given predicate p holds for all entries of this NEMap, otherwise false. */ def forall(p: ((K, V)) => Boolean): Boolean = toMap.forall(p) /** * Applies a function f to all entries of this NEMap. * * @param f the function that is applied for its side-effect to every entry. The result of function f is discarded. */ def foreach(f: ((K, V)) => Unit): Unit = toMap.foreach(f) /** * Partitions this NEMap into a map of NEMaps according to some discriminator function. * * @param f the discriminator function. * @return A map from keys to NEMaps such that the following invariant holds: * *
    * (NEMap.toMap partition f)(k) = xs filter (x => f(x) == k)
    * 
* *

* That is, every key k is bound to a NEMap of those elements x for which f(x) equals k. *

*/ def groupBy(f: ((K, V)) => K): Map[K, NEMap[K, V]] = { val mapKToMap = toMap.groupBy(f) mapKToMap.view.mapValues { list => new NEMap(list) }.toMap } /** * Partitions entries into fixed size NEMaps. * * @param size the number of entries per group * @return An iterator producing NEMaps of size size, except the last will be truncated if the entries don't divide evenly. */ def grouped(size: Int): Iterator[NEMap[K, V]] = { val itOfMap = toMap.grouped(size) itOfMap.map { list => new NEMap(list) } } /** * Returns true to indicate this NEMap has a definite size, since all NEMaps are strict collections. */ def hasDefiniteSize: Boolean = true // override def hashCode: Int = toMap.hashCode /** * Selects the first element of this NEMap. * * @return the first element of this NEMap. */ def head: (K, V) = toMap.head def tail: Map[K, V] = toMap.tail /** * Tests whether this NEMap contains given key. * * @param key the key to test * @return true if this NEMap contains a binding for the given key, false otherwise. */ def isDefinedAt(key: K): Boolean = toMap.isDefinedAt(key) /** * Returns false to indicate this NEMap, like all NEMaps, is non-empty. * * @return false */ def isEmpty: Boolean = false /** * Returns true to indicate this NEMap, like all NEMaps, can be traversed repeatedly. * * @return true */ def isTraversableAgain: Boolean = true /** * Creates and returns a new iterator over all elements contained in this NEMap. * * @return the new iterator */ def iterator: Iterator[(K, V)] = toMap.iterator /** * Selects the last entry of this NEMap. * * @return the last entry of this NEMap. */ def last: (K, V) = toMap.last /** * Builds a new NEMap by applying a function to all entries of this NEMap. * * @tparam K1 the key type of the returned NEMap. * @tparam V1 the value type of the returned NEMap. * @param f the function to apply to each element. * @return a new NEMap resulting from applying the given function f to each element of this NEMap and collecting the results. */ def map[K1, V1](f: ((K, V)) => (K1, V1)): NEMap[K1, V1] = new NEMap(toMap.map(f)) /** * Finds the largest entry. * * @return the largest entry of this NEMap. */ def max[U >: (K, V)](implicit cmp: Ordering[U]): (K, V) = toMap.max(cmp) /** * Finds the largest result after applying the given function to every entry. * * @return the largest result of applying the given function to every entry of this NEMap. */ def maxBy[U](f: ((K, V)) => U)(implicit cmp: Ordering[U]): (K, V) = toMap.maxBy(f)(cmp) /** * Finds the smallest entry. * * @return the smallest entry of this NEMap. */ def min[U >: (K, V)](implicit cmp: Ordering[U]): (K, V) = toMap.min(cmp) /** * Finds the smallest result after applying the given function to every entry. * * @return the smallest result of applying the given function to every entry of this NEMap. */ def minBy[U](f: ((K, V)) => U)(implicit cmp: Ordering[U]): (K, V) = toMap.minBy(f)(cmp) /** * Displays all entries of this NEMap in a string. * * @return a string representation of this NEMap. In the resulting string, the result of invoking toString on all entries of this * NEMap follow each other without any separator string. */ def mkString: String = toMap.mkString /** * Displays all entries of this NEMap in a string using a separator string. * * @param sep the separator string * @return a string representation of this NEMap. In the resulting string, the result of invoking toString on all entries of this * NEMap are separated by the string sep. */ def mkString(sep: String): String = toMap.mkString(sep) /** * Displays all entries of this NEMap in a string using start, end, and separator strings. * * @param start the starting string. * @param sep the separator string. * @param end the ending string. * @return a string representation of this NEMap. The resulting string begins with the string start and ends with the string * end. Inside, In the resulting string, the result of invoking toString on all entries of this NEMap are * separated by the string sep. */ def mkString(start: String, sep: String, end: String): String = toMap.mkString(start, sep, end) /** * Returns true to indicate this NEMap, like all NEMaps, is non-empty. * * @return true */ def nonEmpty: Boolean = true /** * The result of multiplying all the entries of this NEMap. * *

* This method can be invoked for any NEMap[T] for which an implicit Numeric[T] exists. *

* * @return the product of all elements */ def product[U >: (K, V)](implicit num: Numeric[U]): U = toMap.product(num) /** * Reduces the entries of this NEMap using the specified associative binary operator. * *

* The order in which operations are performed on entries is unspecified and may be nondeterministic. *

* * @tparam U a type parameter for the binary operator, a supertype of T. * @param op a binary operator that must be associative. * @return the result of applying reduce operator op between all the elements of this NEMap. */ def reduce[U >: (K, V)](op: (U, U) => U): U = toMap.reduce(op) /** * Applies a binary operator to all entries of this NEMap, going left to right. * * @tparam U the result type of the binary operator. * @param op the binary operator. * @return the result of inserting op between consecutive entries of this NEMap, going left to right: * *
    * op(...op(op(x_1, x_2), x_3), ..., x_n)
    * 
* *

* where x1, ..., xn are the elements of this NEMap. *

*/ def reduceLeft[U >: (K, V)](op: (U, (K, V)) => U): U = toMap.reduceLeft(op) /** * Applies a binary operator to all entries of this NEMap, going left to right, returning the result in a Some. * * @tparam U the result type of the binary operator. * @param op the binary operator. * @return a Some containing the result of reduceLeft(op) *

*/ def reduceLeftOption[U >: (K, V)](op: (U, (K, V)) => U): Option[U] = toMap.reduceLeftOption(op) def reduceOption[U >: (K, V)](op: (U, U) => U): Option[U] = toMap.reduceOption(op) /** * Applies a binary operator to all entries of this NEMap, going right to left. * * @tparam U the result of the binary operator * @param op the binary operator * @return the result of inserting op between consecutive entries of this NEMap, going right to left: * *
    * op(x_1, op(x_2, ... op(x_{n-1}, x_n)...))
    * 
* *

* where x1, ..., xn are the entries of this NEMap. *

*/ def reduceRight[U >: (K, V)](op: ((K, V), U) => U): U = toMap.reduceRight(op) /** * Applies a binary operator to all entries of this NEMap, going right to left, returning the result in a Some. * * @tparam U the result of the binary operator * @param op the binary operator * @return a Some containing the result of reduceRight(op) */ def reduceRightOption[U >: (K, V)](op: ((K, V), U) => U): Option[U] = toMap.reduceRightOption(op) /** * Checks if the given NEMap contains the same entries in the same order as this NEMap. * * @param that the NEMap with which to compare * @return true, if both this and the given NEMap contain the same entries * in the same order, false otherwise. */ def sameElements[V1 >: V](that: NEMap[K, V1]): Boolean = toMap == that.toMap /** * Computes a prefix scan of the entries of this NEMap. * *

* @note The neutral element z may be applied more than once. *

* * @param z a neutral element for the scan operation; may be added to the result an arbitrary number of * times, and must not change the result (e.g., Nil for list concatenation, * 0 for addition, or 1 for multiplication.) * @param op a binary operator that must be associative * @return a new NEMap containing the prefix scan of the elements in this NEMap */ def scan[V1 >: V](z: (K, V1))(op: ((K, V1), (K, V1)) => (K, V1)): NEMap[K, V1] = new NEMap(toMap.scan(z)(op).toMap) /** * Groups entries in fixed size blocks by passing a “sliding window” over them (as opposed to partitioning them, as is done in grouped.) * * @param size the number of entries per group * @return an iterator producing NEMaps of size size, except the last and the only element will be truncated * if there are fewer entries than size. */ def sliding(size: Int): Iterator[NEMap[K, V]] = toMap.sliding(size).map(new NEMap(_)) /** * Groups entries in fixed size blocks by passing a “sliding window” over them (as opposed to partitioning them, as is done in grouped.), * moving the sliding window by a given step each time. * * @param size the number of entries per group * @param step the distance between the first entries of successive groups * @return an iterator producing NEMaps of size size, except the last and the only element will be truncated * if there are fewer elements than size. */ def sliding(size: Int, step: Int): Iterator[NEMap[K, V]] = toMap.sliding(size, step).map(new NEMap(_)) /** * The size of this NEMap. * *

* @note length and size yield the same result, which will be >= 1. *

* * @return the number of elements in this NEMap. */ def size: Int = toMap.size /** * Returns "NEMap", the prefix of this object's toString representation. * * @return the string "NEMap" */ def stringPrefix: String = "NEMap" /** * The result of summing all the elements of this NEMap. * *

* This method can be invoked for any NEMap[T] for which an implicit Numeric[T] exists. *

* * @return the sum of all elements */ def sum[U >: (K, V)](implicit num: Numeric[U]): U = toMap.sum(num) /** * Converts this NEMap into a collection of type Col by copying all entries. * * @tparam C1 the collection type to build. * @return a new collection containing all entries of this NEMap. */ def to[C1](factory: Factory[(K, V), C1]): C1 = factory.fromSpecific(iterator) /** * Converts this NEMap to an array. * * @return an array containing all entries of this NEMap. A ClassTag must be available for the entry type of this NEMap. */ def toArray[U >: (K, V)](implicit classTag: ClassTag[U]): Array[U] = toMap.toArray /** * Converts this NEMap to a Vector. * * @return a Vector containing all entries of this NEMap. */ def toVector: Vector[(K, V)] = toMap.toVector /** * Converts this NEMap to a mutable buffer. * * @return a buffer containing all entries of this NEMap. */ def toBuffer[U >: (K, V)]: mutable.Buffer[U] = toMap.toBuffer /** * Converts this NEMap to an immutable IndexedSeq. * * @return an immutable IndexedSeq containing all entries of this NEMap. */ def toIndexedSeq: collection.immutable.IndexedSeq[(K, V)] = toMap.toVector /** * Converts this NEMap to an iterable collection. * * @return an Iterable containing all entries of this NEMap. */ def toIterable: Iterable[(K, V)] = toMap /** * Returns an Iterator over the entries in this NEMap. * * @return an Iterator containing all entries of this NEMap. */ def toIterator: Iterator[(K, V)] = toMap.iterator /** * Converts this NEMap to an immutable IndexedSeq. * * @return an immutable IndexedSeq containing all entries of this NEMap. */ def toSeq: collection.immutable.Seq[(K, V)] = collection.immutable.Seq.empty[(K, V)] ++ toMap.toSeq /** * Converts this NEMap to a set. * * @return a set containing all entries of this NEMap. */ def toSet[U >: (K, V)]: Set[U] = toMap.toSet /** * Returns a string representation of this NEMap. * * @return the string "NEMap" followed by the result of invoking toString on * this NEMap's elements, surrounded by parentheses. */ override def toString: String = "NEMap(" + toMap.mkString(", ") + ")" /** * Converts this NEMap of pairs into two Iterables of the first and second half of each pair. * * @tparam L the type of the first half of the element pairs * @tparam R the type of the second half of the element pairs * @param asPair an implicit conversion that asserts that the element type of this NEMap is a pair. * @return a pair of NEMaps, containing the first and second half, respectively, of each element pair of this NEMap. */ def unzip[L, R](implicit asPair: ((K, V)) => (L, R)): (scala.collection.immutable.Iterable[L], scala.collection.immutable.Iterable[R]) = toMap.unzip /** * Converts this NEMap of triples into three NEMaps of the first, second, and and third entry of each triple. * * @tparam L the type of the first member of the entry triples * @tparam R the type of the second member of the entry triples * @tparam R the type of the third member of the entry triples * @param asTriple an implicit conversion that asserts that the entry type of this NEMap is a triple. * @return a triple of NEMaps, containing the first, second, and third member, respectively, of each entry triple of this NEMap. */ def unzip3[L, M, R]( implicit asTriple: ((K, V)) => (L, M, R) ): (scala.collection.immutable.Iterable[L], scala.collection.immutable.Iterable[M], scala.collection.immutable.Iterable[R]) = toMap.unzip3 /** * A copy of this NEMap with one single replaced entry. * * @param key the key of the replacement * @param value the replacing value * @return a copy of this NEMap with the value at key replaced by the given value. */ def updated[V1 >: V](key: K, value: V1): NEMap[K, V1] = new NEMap(toMap.updated(key, value)) /** * Returns a NEMap formed from this NEMap and an iterable collection by combining corresponding * entries in pairs. If one of the two collections is shorter than the other, placeholder entries will be used to extend the * shorter collection to the length of the longer. * * @tparam O the type of the second half of the returned pairs * @tparam V1 the subtype of the value type of this NEMap * @param other the Iterable providing the second half of each result pair * @param thisElem the element to be used to fill up the result if this NEMap is shorter than that Iterable. * @param otherElem the element to be used to fill up the result if that Iterable is shorter than this NEMap. * @return a new NEMap containing pairs consisting of corresponding entries of this NEMap and that. The * length of the returned collection is the maximum of the lengths of this NEMap and that. If this NEMap * is shorter than that, thisElem values are used to pad the result. If that is shorter than this * NEMap, thatElem values are used to pad the result. */ def zipAll[O, V1 >: V](other: collection.Iterable[O], thisElem: (K, V1), otherElem: O): NEMap[(K, V1), O] = new NEMap(toMap.zipAll(other, thisElem, otherElem).toMap) /** * Zips this NEMap with its indices. * * @return A new NEMap containing pairs consisting of all elements of this NEMap paired with their index. Indices start at 0. */ def zipWithIndex[V1 >: V]: NEMap[(K, V1), Int] = new NEMap(toMap.zipWithIndex.toMap) } /** * Companion object for class NEMap. */ object NEMap { /** * Constructs a new NEMap given at least one element. * * @tparam K the type of the key contained in the new NEMap * @tparam V the type of the value contained in the new NEMap * @param firstElement the first element (with index 0) contained in this NEMap * @param otherElements a varargs of zero or more other elements (with index 1, 2, 3, ...) contained in this NEMap */ @inline def apply[K, V](firstElement: (K, V), otherElements: (K, V)*): NEMap[K, V] = new NEMap(otherElements.toMap + firstElement) /** * Variable argument extractor for NEMaps. * * @tparam K the type of the key contained in the NEMap * @tparam V the type of the value contained in the NEMap * @param NEMap: the NEMap containing the elements to extract * @return an Seq containing this NEMaps elements, wrapped in a Some */ @inline def unapplySeq[K, V](NEMap: NEMap[K, V]): Some[Seq[(K, V)]] = Some(NEMap.toSeq) /** * Optionally construct a NEMap containing the elements, if any, of a given Seq. * * @tparam K the type of the key contained in the new NEMap * @tparam V the type of the value contained in the new NEMap * @param seq the Seq with which to construct a NEMap * @return a NEMap containing the elements of the given Seq, if non-empty, wrapped in * a Some; else None if the Seq is empty */ @inline def from[K, V](seq: Seq[(K, V)]): Option[NEMap[K, V]] = seq.headOption match { case None => None case Some(first) => Some(new NEMap(scala.collection.immutable.Map.empty[K, V] ++ seq.tail.toMap + first)) } @inline def from[K, V](map: scala.collection.Map[K, V]): Option[NEMap[K, V]] = { if (map.isEmpty) None else Some(new NEMap(scala.collection.immutable.Map.empty[K, V] ++ map)) } @inline def from[K, V](map: scala.collection.immutable.Map[K, V]): Option[NEMap[K, V]] = { if (map.isEmpty) None else Some(new NEMap(map)) } @inline def unsafeFrom[K, V](set: scala.collection.immutable.Map[K, V]): NEMap[K, V] = { require(set.nonEmpty) new NEMap(set) } implicit final class OptionOps[K, +V](private val option: Option[NEMap[K, V]]) extends AnyVal { @inline def fromNEMap: Map[K, V] = if (option.isEmpty) Map.empty else option.get.toMap } @inline implicit def asIterable[K, V](ne: NEMap[K, V]): IterableOnce[(K, V)] = ne.toIterable }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy