izumi.fundamentals.collections.nonempty.NEMap.scala Maven / Gradle / Ivy
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 NEMap
s
*
*
* 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 NEMap
s
*
*
* 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 NEMap
s 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 NEMap
s.
*
* @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 NEMap
s.
*/
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 NEMap
s according to some discriminator function.
*
* @param f the discriminator function.
* @return A map from keys to NEMap
s 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 NEMap
s.
*
* @param size the number of entries per group
* @return An iterator producing NEMap
s 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 NEMap
s 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 NEMap
s, is non-empty.
*
* @return false
*/
def isEmpty: Boolean = false
/**
* Returns true
to indicate this NEMap
, like all NEMap
s, 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 NEMap
s, 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 NEMap
s 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 NEMap
s 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 Iterable
s 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 NEMap
s, 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 NEMap
s 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 NEMap
s, 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 NEMap
s.
*
* @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 NEMap
s 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
}