org.scalactic.anyvals.NonEmptyMap.scala Maven / Gradle / Ivy
/*
* Copyright 2001-2013 Artima, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.scalactic.anyvals
import scala.annotation.unchecked.{ uncheckedVariance => uV }
import scala.collection.GenIterable
import scala.collection.GenSeq
import scala.collection.GenTraversableOnce
import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Buffer
import scala.reflect.ClassTag
import scala.collection.immutable
import scala.collection.mutable.ArrayBuffer
import org.scalactic.Every
// 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 NonEmptyMap
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 Every
.
*
*
* Constructing NonEmptyMap
s
*
*
* You can construct a NonEmptyMap
by passing one or more elements to the NonEmptyMap.apply
factory method:
*
*
*
* scala> NonEmptyMap(1 -> "one", 2 -> "two", 3 -> "three")
* res0: org.scalactic.anyvals.NonEmptyMap[Int, String] = NonEmptyMap(1 -> "one", 2 -> "two", 3 -> "three")
*
*
* Working with NonEmptyMap
s
*
*
* NonEmptyMap
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, NonEmptyMap
defines a method corresponding to every such Map
* method. Here are an example:
*
*
*
* NonEmptyMap(1 -> "one", 2 -> "two", 3 -> "three").map(t => (t._1 + 1, t._2)) // Result: NonEmptyMap(2 -> "one", 3 -> "two", 4 -> "three")
*
*
*
* NonEmptyMap
does not currently define any methods corresponding to Map
methods that could result in
* an empty Map
. However, an implicit converison from NonEmptyMap
to Map
* is defined in the NonEmptyMap
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 NonEmptyMap
, even though filter
could result
* in an empty map—but the result type will be Map
instead of NonEmptyMap
:
*
*
*
* NonEmptyMap(1 -> "one", 2 -> "two", 3 -> "three").filter(_._1 < 10) // Result: Map(1 -> "one", 2 -> "two", 3 -> "three")
* NonEmptyMap(1 -> "one", 2 -> "two", 3 -> "three").filter(_._ 1> 10) // Result: Map()
*
*
*
*
* You can use NonEmptyMap
s in for
expressions. The result will be an NonEmptyMap
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) <- NonEmptyMap(1 -> "one", 2 -> "two", 3 -> "three")) yield (i + 1, j)
* res0: org.scalactic.anyvals.NonEmptyMap[Int, String] = NonEmptyMap(2 -> "one", 3 -> "two", 4 -> "three")
*
* scala> for ((i, j) <- NonEmptyMap(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 NonEmptyMap
* @tparam V the type of value contained in this NonEmptyMap
*/
final class NonEmptyMap[K, +V] private (val toMap: Map[K, V]) extends AnyVal {
/**
* Returns a new NonEmptyMap
containing the entries of this NonEmptyMap
and the entries of the passed NonEmptyMap
.
* The entry type of the resulting NonEmptyMap
is the most specific superclass encompassing the entry types of this and the passed NonEmptyMap
.
*
* @tparam V1 the value type of the returned NonEmptyMap
* @param other the NonEmptyMap
to append
* @return a new NonEmptyMap
that contains all the elements of this NonEmptyMap
and all elements of other
.
*/
def ++[V1 >: V](other: NonEmptyMap[K, V1]): NonEmptyMap[K, V1] = new NonEmptyMap(toMap ++ other.toMap)
/**
* Returns a new NonEmptyMap
containing the entries of this NonEmptyMap
and the entries of the passed Every
.
* The entry type of the resulting NonEmptyMap
is the most specific superclass encompassing the entry types of this NonEmptyMap
and the passed Every
.
*
* @tparam V1 the value type of the returned NonEmptyMap
* @param other the Every
to append
* @return a new NonEmptyMap
that contains all the entries of this NonEmptyMap
and all elements of other
.
*/
def ++[V1 >: V](other: Every[(K, V1)]): NonEmptyMap[K, V1] = new NonEmptyMap(toMap ++ other.toVector)
// TODO: Have I added these extra ++, etc. methods to Every that take a NonEmptyMap?
/**
* Returns a new NonEmptyMap
containing the entries of this NonEmptyMap
and the entries of the passed GenTraversableOnce
.
* The entry type of the resulting NonEmptyMap
is the most specific superclass encompassing the entry types of this NonEmptyMap
* and the passed GenTraversableOnce
.
*
* @tparam V1 the value type of the returned NonEmptyMap
* @param other the GenTraversableOnce
to append
* @return a new NonEmptyMap
that contains all the elements of this NonEmptyMap
followed by all elements of other
.
*/
def ++[V1 >: V](other: org.scalactic.ColCompatHelper.IterableOnce[(K, V1)]): NonEmptyMap[K, V1] =
if (other.isEmpty) this else new NonEmptyMap(toMap ++ other.toMap)
/**
* Returns a new NonEmptyMap
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 NonEmptyMap
* @return a new NonEmptyMap
consisting of element
followed by all elements of this NonEmptyMap
.
*/
final def +:[V1 >: V](entry: (K, V1)): NonEmptyMap[K, V1] = new NonEmptyMap(toMap + entry)
/**
* As with ++
, returns a new NonEmptyMap
containing the entries of this NonEmptyMap
and the entries of the passed NonEmptyMap
.
* The entry type of the resulting NonEmptyMap
is the most specific superclass encompassing the entry types of this and the passed NonEmptyMap
.
*
* 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 NonEmptyMap
* @param other the NonEmptyMap
to add
* @return a new NonEmptyMap
that contains all the elements of this NonEmptyMap
and all elements of other
.
*/
def ++:[V1 >: V](other: NonEmptyMap[K, V1]): NonEmptyMap[K, V1] = new NonEmptyMap(toMap ++ other.toMap)
/**
* As with ++
, returns a new NonEmptyMap
containing the entries of this NonEmptyMap
and the entries of the passed Every
.
* The entry type of the resulting NonEmptyMap
is the most specific superclass encompassing the entry types of this NonEmptyMap
and the passed Every
.
*
* 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 NonEmptyMap
* @param other the Every
to append
* @return a new NonEmptyMap
that contains all the entries of this NonEmptyMap
and all elements of other
.
*/
def ++:[V1 >: V](other: Every[(K, V1)]): NonEmptyMap[K, V1] = new NonEmptyMap(toMap ++ other.toVector)
/**
* Returns a new NonEmptyMap
containing the entries of this NonEmptyMap
and the entries of the passed GenTraversableOnce
.
* The entry type of the resulting NonEmptyMap
is the most specific superclass encompassing the entry types of this NonEmptyMap
* and the passed GenTraversableOnce
.
*
* @tparam V1 the value type of the returned NonEmptyMap
* @param other the GenTraversableOnce
to append
* @return a new NonEmptyMap
that contains all the elements of this NonEmptyMap
followed by all elements of other
.
*/
def ++:[V1 >: V](other: org.scalactic.ColCompatHelper.IterableOnce[(K, V1)]): NonEmptyMap[K, V1] =
if (other.isEmpty) this else new NonEmptyMap(toMap ++ other.toMap)
/**
* Returns a new NonEmptyMap
with the given entry added.
*
* @param entry the entry to add to this NonEmptyMap
* @return a new NonEmptyMap
consisting of all entries of this NonEmptyMap
and entry
.
*/
def +[V1 >: V](entry: (K, V1)): NonEmptyMap[K, V1] = new NonEmptyMap(toMap + entry)
/**
* Returns a new NonEmptyMap
with the given entries added.
*
* @param entries the entries to add to this NonEmptyMap
* @return a new NonEmptyMap
consisting of all entries of this NonEmptyMap
and entries
.
*/
def +[V1 >: V](entries: (K, V1)*): NonEmptyMap[K, V1] = new NonEmptyMap(toMap ++ entries)
/**
* Appends all entries of this NonEmptyMap
to a string builder. The written text will consist of a concatenation of the result of invoking toString
* on of every entry of this NonEmptyMap
, 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.
*/
final def addString(sb: StringBuilder): StringBuilder = toMap.addString(sb)
/**
* Appends all entries of this NonEmptyMap
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 NonEmptyMap
, 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.
*/
final def addString(sb: StringBuilder, sep: String): StringBuilder = toMap.addString(sb, sep)
/**
* Appends all entries of this NonEmptyMap
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 NonEmptyMap
,
* 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.
*/
final 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 NonEmptyMap
.
*
* @return the value of this NonEmptyMap
at key k
.
*/
final def apply(k: K): V = toMap(k)
/**
* Finds the first entry of this NonEmptyMap
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.
*/
final def collectFirst[U](pf: PartialFunction[(K, V), U]): Option[U] = toMap.collectFirst(pf)
/**
* Indicates whether this NonEmptyMap
contains a binding for given key.
*
* @param key the key to look for
* @return true if this NonEmptyMap
has a binding that is equal (as determined by ==)
to key
, false otherwise.
*/
final def contains(key: K): Boolean = toMap.contains(key)
/**
* Copies entries of this NonEmptyMap
to an array. Fills the given array arr
with entries of this NonEmptyMap
. Copying
* will stop once either the end of the current NonEmptyMap
is reached, or the end of the array is reached.
*
* @param arr the array to fill
*/
final def copyToArray[V1 >: V](arr: Array[(K, V1)]): Unit = toMap.copyToArray(arr)
/**
* Copies entries of this NonEmptyMap
to an array. Fills the given array arr
with entries of this NonEmptyMap
, beginning at
* index start
. Copying will stop once either the end of the current NonEmptyMap
is reached, or the end of the array is reached.
*
* @param arr the array to fill
* @param start the starting index
*/
final def copyToArray[V1 >: V](arr: Array[(K, V1)], start: Int): Unit = toMap.copyToArray(arr, start)
/**
* Copies entries of this NonEmptyMap
to an array. Fills the given array arr
with at most len
entries of this NonEmptyMap
, beginning at
* index start
. Copying will stop once either the end of the current NonEmptyMap
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
*/
final def copyToArray[V1 >: V](arr: Array[(K, V1)], start: Int, len: Int): Unit = toMap.copyToArray(arr, start, len)
/**
* Copies all elements of this NonEmptyMap
to a buffer.
*
* @param buf the buffer to which elements are copied
*/
final def copyToBuffer[V1 >: V](buf: Buffer[(K, V1)]): Unit = toMap.copyToBuffer(buf)
/**
* Counts the number of elements in this NonEmptyMap
that satisfy a predicate.
*
* @param p the predicate used to test elements.
* @return the number of elements satisfying the predicate p
.
*/
final def count(p: ((K, V)) => Boolean): Int = toMap.count(p)
/*
override def equals(o: Any): Boolean =
o match {
case nonEmptyMap: NonEmptyMap[_] => toMap == nonEmptyMap.toMap
case _ => false
}
*/
/**
* Indicates whether a predicate holds for at least one of the entries of this NonEmptyMap
.
*
* @param p the predicate used to test entries.
* @return true
if the given predicate p
holds for some of the entries of this NonEmptyMap
, otherwise false
.
*/
final def exists(p: ((K, V)) => Boolean): Boolean = toMap.exists(p)
/**
* Finds the first entry of this NonEmptyMap
that satisfies the given predicate, if any.
*
* @param p the predicate used to test elements
* @return an Some
containing the first element in this NonEmptyMap
that satisfies p
, or None
if none exists.
*/
final def find(p: ((K, V)) => Boolean): Option[(K, V)] = toMap.find(p)
/**
* Builds a new NonEmptyMap
by applying a function to all entries of this NonEmptyMap
and using the entries of the resulting NonEmptyMap
s.
*
* @tparam K1 the key type of the returned NonEmptyMap
* @tparam V1 the value type of the returned NonEmptyMap
* @param f the function to apply to each entry.
* @return a new NonEmptyMap
containing entries obtained by applying the given function f
to each entry of this NonEmptyMap
and concatenating
* the entries of resulting NonEmptyMap
s.
*/
final def flatMap[K1, V1](f: ((K, V)) => NonEmptyMap[K1, V1]): NonEmptyMap[K1, V1] = {
val buf = new ArrayBuffer[(K1, V1)]
for (ele <- toMap)
buf ++= f(ele).toMap
new NonEmptyMap(buf.toMap)
}
/**
* Folds the entries of this NonEmptyMap
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
*/
final 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 NonEmptyMap
, 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 NonEmptyMap
, 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 NonEmptyMap
.
*
*/
final def foldLeft[B](z: B)(op: (B, (K, V)) => B): B = toMap.foldLeft(z)(op)
/**
* Applies a binary operator to all entries of this NonEmptyMap
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 NonEmptyMap
, 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 NonEmptyMap
.
*
*/
final 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 NonEmptyMap
.
*
* @param p the predicate used to test entries.
* @return true
if the given predicate p
holds for all entries of this NonEmptyMap
, otherwise false
.
*/
final def forall(p: ((K, V)) => Boolean): Boolean = toMap.forall(p)
/**
* Applies a function f
to all entries of this NonEmptyMap
.
*
* @param f the function that is applied for its side-effect to every entry. The result of function f
is discarded.
*/
final def foreach(f: ((K, V)) => Unit): Unit = toMap.foreach(f)
/**
* Partitions this NonEmptyMap
into a map of NonEmptyMap
s according to some discriminator function.
*
* @param f the discriminator function.
* @return A map from keys to NonEmptyMap
s such that the following invariant holds:
*
*
* (nonEmptyMap.toMap partition f)(k) = xs filter (x => f(x) == k)
*
*
*
* That is, every key k
is bound to a NonEmptyMap
of those elements x
for which f(x)
equals k
.
*
*/
final def groupBy(f: ((K, V)) => K): Map[K, NonEmptyMap[K, V]] = {
val mapKToMap = toMap.groupBy(f)
mapKToMap.mapValues { list => new NonEmptyMap(list) }.toMap
}
/**
* Partitions entries into fixed size NonEmptyMap
s.
*
* @param size the number of entries per group
* @return An iterator producing NonEmptyMap
s of size size
, except the last will be truncated if the entries don't divide evenly.
*/
final def grouped(size: Int): Iterator[NonEmptyMap[K, V]] = {
val itOfMap = toMap.grouped(size)
itOfMap.map { list => new NonEmptyMap(list) }
}
/**
* Returns true
to indicate this NonEmptyMap
has a definite size, since all NonEmptyMap
s are strict collections.
*/
final def hasDefiniteSize: Boolean = true
// override def hashCode: Int = toMap.hashCode
/**
* Selects the first element of this NonEmptyMap
.
*
* @return the first element of this NonEmptyMap
.
*/
final def head: (K, V) = toMap.head
// Methods like headOption I can't get rid of because of the implicit conversion to GenTraversable.
// Users can call any of the methods I've left out on a NonEmptyMap, and get whatever Map would return
// for that method call. Eventually I'll probably implement them all to save the implicit conversion.
/**
* Selects the first element of this NonEmptyMap
and returns it wrapped in a Some
.
*
* @return the first element of this NonEmptyMap
, wrapped in a Some
.
*/
final def headOption: Option[(K, V)] = toMap.headOption
/**
* Tests whether this NonEmptyMap
contains given key.
*
* @param key the key to test
* @return true if this NonEmptyMap
contains a binding for the given key
, false
otherwise.
*/
final def isDefinedAt(key: K): Boolean = toMap.isDefinedAt(key)
/**
* Returns false
to indicate this NonEmptyMap
, like all NonEmptyMap
s, is non-empty.
*
* @return false
*/
final def isEmpty: Boolean = false
/**
* Returns true
to indicate this NonEmptyMap
, like all NonEmptyMap
s, can be traversed repeatedly.
*
* @return true
*/
final def isTraversableAgain: Boolean = true
/**
* Creates and returns a new iterator over all elements contained in this NonEmptyMap
.
*
* @return the new iterator
*/
final def iterator: Iterator[(K, V)] = toMap.iterator
/**
* Selects the last entry of this NonEmptyMap
.
*
* @return the last entry of this NonEmptyMap
.
*/
final def last: (K, V) = toMap.last
/**
* Returns the last element of this NonEmptyMap
, wrapped in a Some
.
*
* @return the last element, wrapped in a Some
.
*/
final def lastOption: Option[(K, V)] = toMap.lastOption // Will always return a Some
/**
* Builds a new NonEmptyMap
by applying a function to all entries of this NonEmptyMap
.
*
* @tparam K1 the key type of the returned NonEmptyMap
.
* @tparam V1 the value type of the returned NonEmptyMap
.
* @param f the function to apply to each element.
* @return a new NonEmptyMap
resulting from applying the given function f
to each element of this NonEmptyMap
and collecting the results.
*/
final def map[K1, V1](f: ((K, V)) => (K1, V1)): NonEmptyMap[K1, V1] =
new NonEmptyMap(toMap.map(f))
/**
* Finds the largest entry.
*
* @return the largest entry of this NonEmptyMap
.
*/
final 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 NonEmptyMap
.
*/
final 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 NonEmptyMap
.
*/
final 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 NonEmptyMap
.
*/
final def minBy[U](f: ((K, V)) => U)(implicit cmp: Ordering[U]): (K, V) = toMap.minBy(f)(cmp)
/**
* Displays all entries of this NonEmptyMap
in a string.
*
* @return a string representation of this NonEmptyMap
. In the resulting string, the result of invoking toString
on all entries of this
* NonEmptyMap
follow each other without any separator string.
*/
final def mkString: String = toMap.mkString
/**
* Displays all entries of this NonEmptyMap
in a string using a separator string.
*
* @param sep the separator string
* @return a string representation of this NonEmptyMap
. In the resulting string, the result of invoking toString
on all entries of this
* NonEmptyMap
are separated by the string sep
.
*/
final def mkString(sep: String): String = toMap.mkString(sep)
/**
* Displays all entries of this NonEmptyMap
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 NonEmptyMap
. 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 NonEmptyMap
are
* separated by the string sep
.
*/
final def mkString(start: String, sep: String, end: String): String = toMap.mkString(start, sep, end)
/**
* Returns true
to indicate this NonEmptyMap
, like all NonEmptyMap
s, is non-empty.
*
* @return true
*/
final def nonEmpty: Boolean = true
/**
* The result of multiplying all the entries of this NonEmptyMap
.
*
*
* This method can be invoked for any NonEmptyMap[T]
for which an implicit Numeric[T]
exists.
*
*
* @return the product of all elements
*/
final def product[U >: (K, V)](implicit num: Numeric[U]): U = toMap.product(num)
/**
* Reduces the entries of this NonEmptyMap
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 NonEmptyMap
.
*/
final def reduce[U >: (K, V)](op: (U, U) => U): U = toMap.reduce(op)
/**
* Applies a binary operator to all entries of this NonEmptyMap
, 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 NonEmptyMap
, going left to right:
*
*
* op(...op(op(x_1, x_2), x_3), ..., x_n)
*
*
*
* where x1, ..., xn are the elements of this NonEmptyMap
.
*
*/
final def reduceLeft[U >: (K, V)](op: (U, (K, V)) => U): U = toMap.reduceLeft(op)
/**
* Applies a binary operator to all entries of this NonEmptyMap
, 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)
*
*/
final def reduceLeftOption[U >: (K, V)](op: (U, (K, V)) => U): Option[U] = toMap.reduceLeftOption(op)
final def reduceOption[U >: (K, V)](op: (U, U) => U): Option[U] = toMap.reduceOption(op)
/**
* Applies a binary operator to all entries of this NonEmptyMap
, 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 NonEmptyMap
, going right to left:
*
*
* op(x_1, op(x_2, ... op(x_{n-1}, x_n)...))
*
*
*
* where x1, ..., xn are the entries of this NonEmptyMap
.
*
*/
final def reduceRight[U >: (K, V)](op: ((K, V), U) => U): U = toMap.reduceRight(op)
/**
* Applies a binary operator to all entries of this NonEmptyMap
, 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)
*/
final def reduceRightOption[U >: (K, V)](op: ((K, V), U) => U): Option[U] = toMap.reduceRightOption(op)
/**
* Checks if the given GenIterable
contains the same entries in the same order as this NonEmptyMap
.
*
* @param that the GenIterable
with which to compare
* @return true
, if both this NonEmptyMap
and the given GenIterable
contain the same entries
* in the same order, false
otherwise.
*/
final def sameElements[U >: (K, V)](that: GenIterable[U]): Boolean = toMap.sameElements(that)
/**
* Checks if the given Every
contains the same entries in the same order as this NonEmptyMap
.
*
* @param that the Every
with which to compare
* @return true
, if both this and the given Every
contain the same entries
* in the same order, false
otherwise.
*/
final def sameElements[U >: (K, V)](that: Every[U]): Boolean = toMap.sameElements(that.toVector)
/**
* Checks if the given NonEmptyMap
contains the same entries in the same order as this NonEmptyMap
.
*
* @param that the NonEmptyMap
with which to compare
* @return true
, if both this and the given NonEmptyMap
contain the same entries
* in the same order, false
otherwise.
*/
final def sameElements[V1 >: V](that: NonEmptyMap[K, V1]): Boolean = toMap.sameElements(that.toMap)
/**
* Computes a prefix scan of the entries of this NonEmptyMap
.
*
*
* 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 NonEmptyMap
containing the prefix scan of the elements in this NonEmptyMap
*/
final def scan[V1 >: V](z: (K, V1))(op: ((K, V1), (K, V1)) => (K, V1)): NonEmptyMap[K, V1] = new NonEmptyMap(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 NonEmptyMap
s of size size
, except the last and the only element will be truncated
* if there are fewer entries than size
.
*/
final def sliding(size: Int): Iterator[NonEmptyMap[K, V]] = toMap.sliding(size).map(new NonEmptyMap(_))
/**
* 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 NonEmptyMap
s of size size
, except the last and the only element will be truncated
* if there are fewer elements than size
.
*/
final def sliding(size: Int, step: Int): Iterator[NonEmptyMap[K, V]] = toMap.sliding(size, step).map(new NonEmptyMap(_))
/**
* The size of this NonEmptyMap
.
*
*
* Note: length
and size
yield the same result, which will be >
= 1.
*
*
* @return the number of elements in this NonEmptyMap
.
*/
final def size: Int = toMap.size
/**
* Returns "NonEmptyMap"
, the prefix of this object's toString
representation.
*
* @return the string "NonEmptyMap"
*/
def stringPrefix: String = "NonEmptyMap"
/**
* The result of summing all the elements of this NonEmptyMap
.
*
*
* This method can be invoked for any NonEmptyMap[T]
for which an implicit Numeric[T]
exists.
*
*
* @return the sum of all elements
*/
final def sum[U >: (K, V)](implicit num: Numeric[U]): U = toMap.sum(num)
import scala.language.higherKinds
/**
* Converts this NonEmptyMap
into a collection of type Col
by copying all entries.
*
* @tparam Col the collection type to build.
* @return a new collection containing all entries of this NonEmptyMap
.
*/
//final def to[Col[_]](implicit cbf: CanBuildFrom[Nothing, (K, V), Col[(K, V) @uV]]): Col[(K, V) @uV] = toMap.to[Col](cbf)
final def to[Col[_]](factory: org.scalactic.ColCompatHelper.Factory[(K, V), Col[(K, V) @ uV]]): Col[(K, V) @ uV] =
toMap.to(factory)
/**
* Converts this NonEmptyMap
to an array.
*
* @return an array containing all entries of this NonEmptyMap
. A ClassTag
must be available for the entry type of this NonEmptyMap
.
*/
final def toArray[U >: (K, V)](implicit classTag: ClassTag[U]): Array[U] = toMap.toArray
/**
* Converts this NonEmptyMap
to a Vector
.
*
* @return a Vector
containing all entries of this NonEmptyMap
.
*/
final def toVector: Vector[(K, V)] = toMap.toVector
/**
* Converts this NonEmptyMap
to a mutable buffer.
*
* @return a buffer containing all entries of this NonEmptyMap
.
*/
final def toBuffer[U >: (K, V)]: Buffer[U] = toMap.toBuffer
/**
* Converts this NonEmptyMap
to an immutable IndexedSeq
.
*
* @return an immutable IndexedSeq
containing all entries of this NonEmptyMap
.
*/
final def toIndexedSeq: collection.immutable.IndexedSeq[(K, V)] = toMap.toVector
/**
* Converts this NonEmptyMap
to an iterable collection.
*
* @return an Iterable
containing all entries of this NonEmptyMap
.
*/
final def toIterable: Iterable[(K, V)] = toMap.toIterable
/**
* Returns an Iterator
over the entries in this NonEmptyMap
.
*
* @return an Iterator
containing all entries of this NonEmptyMap
.
*/
final def toIterator: Iterator[(K, V)] = toMap.toIterator
/**
* Converts this NonEmptyMap
to an immutable IndexedSeq
.
*
* @return an immutable IndexedSeq
containing all entries of this NonEmptyMap
.
*/
final def toSeq: collection.immutable.Seq[(K, V)] = collection.immutable.Seq.empty[(K, V)] ++ toMap.toSeq
/**
* Converts this NonEmptyMap
to a set.
*
* @return a set containing all entries of this NonEmptyMap
.
*/
final def toSet[U >: (K, V)]: Set[U] = toMap.toSet
/**
* Converts this NonEmptyMap
to a stream.
*
* @return a stream containing all entries of this NonEmptyMap
.
*/
final def toStream: Stream[(K, V)] = toMap.toStream
/**
* Returns a string representation of this NonEmptyMap
.
*
* @return the string "NonEmptyMap"
followed by the result of invoking toString
on
* this NonEmptyMap
's elements, surrounded by parentheses.
*/
override def toString: String = "NonEmptyMap(" + toMap.mkString(", ") + ")"
/**
* Converts this NonEmptyMap
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 NonEmptyMap
is a pair.
* @return a pair of NonEmptyMap
s, containing the first and second half, respectively, of each element pair of this NonEmptyMap
.
*/
final def unzip[L, R](implicit asPair: ((K, V)) => (L, R)): (scala.collection.immutable.Iterable[L], scala.collection.immutable.Iterable[R]) = toMap.unzip
/**
* Converts this NonEmptyMap
of triples into three NonEmptyMap
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 NonEmptyMap
is a triple.
* @return a triple of NonEmptyMap
s, containing the first, second, and third member, respectively, of each entry triple of this NonEmptyMap
.
*/
final 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 NonEmptyMap
with one single replaced entry.
*
* @param key the key of the replacement
* @param value the replacing value
* @return a copy of this NonEmptyMap
with the value at key
replaced by the given value
.
*/
final def updated[V1 >: V](key: K, value: V1): NonEmptyMap[K, V1] =
new NonEmptyMap(toMap.updated(key, value))
/**
* Returns a NonEmptyMap
formed from this NonEmptyMap
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 NonEmptyMap
* @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 NonEmptyMap
is shorter than that
Iterable
.
* @param otherElem the element to be used to fill up the result if that
Iterable
is shorter than this NonEmptyMap
.
* @return a new NonEmptyMap
containing pairs consisting of corresponding entries of this NonEmptyMap
and that
. The
* length of the returned collection is the maximum of the lengths of this NonEmptyMap
and that
. If this NonEmptyMap
* is shorter than that
, thisElem
values are used to pad the result. If that
is shorter than this
* NonEmptyMap
, thatElem
values are used to pad the result.
*/
final def zipAll[O, V1 >: V](other: collection.Iterable[O], thisElem: (K, V1), otherElem: O): NonEmptyMap[(K, V1), O] =
new NonEmptyMap(toMap.zipAll(other, thisElem, otherElem).toMap)
/**
* Zips this NonEmptyMap
with its indices.
*
* @return A new NonEmptyMap
containing pairs consisting of all elements of this NonEmptyMap
paired with their index. Indices start at 0.
*/
final def zipWithIndex[V1 >: V]: NonEmptyMap[(K, V1), Int] = new NonEmptyMap(toMap.zipWithIndex.toMap)
}
/**
* Companion object for class NonEmptyMap
.
*/
object NonEmptyMap {
/**
* Constructs a new NonEmptyMap
given at least one element.
*
* @tparam K the type of the key contained in the new NonEmptyMap
* @tparam V the type of the value contained in the new NonEmptyMap
* @param firstElement the first element (with index 0) contained in this NonEmptyMap
* @param otherElements a varargs of zero or more other elements (with index 1, 2, 3, ...) contained in this NonEmptyMap
*/
def apply[K, V](firstElement: (K, V), otherElements: (K, V)*): NonEmptyMap[K, V] = new NonEmptyMap(otherElements.toMap + firstElement)
/**
* Variable argument extractor for NonEmptyMap
s.
*
* @tparam K the type of the key contained in the NonEmptyMap
* @tparam V the type of the value contained in the NonEmptyMap
* @param nonEmptyMap: the NonEmptyMap
containing the elements to extract
* @return an Seq
containing this NonEmptyMap
s elements, wrapped in a Some
*/
def unapplySeq[K, V](nonEmptyMap: NonEmptyMap[K, V]): Option[Seq[(K, V)]] = Some(nonEmptyMap.toSeq)
/**
* Optionally construct a NonEmptyMap
containing the elements, if any, of a given GenSeq
.
*
* @tparam K the type of the key contained in the new NonEmptyMap
* @tparam V the type of the value contained in the new NonEmptyMap
* @param seq the GenSeq
with which to construct a NonEmptyMap
* @return a NonEmptyMap
containing the elements of the given GenSeq
, if non-empty, wrapped in
* a Some
; else None
if the GenSeq
is empty
*/
def from[K, V](seq: GenSeq[(K, V)]): Option[NonEmptyMap[K, V]] =
seq.headOption match {
case None => None
case Some(first) => Some(new NonEmptyMap(scala.collection.immutable.Map.empty[K, V] ++ seq.tail.toMap + first))
}
def from[K, V](map: scala.collection.GenMap[K, V]): Option[NonEmptyMap[K, V]] =
map.headOption match {
case None => None
case Some(first) => Some(new NonEmptyMap(scala.collection.immutable.Map.empty[K, V] ++ map))
}
import scala.language.implicitConversions
/**
* Implicit conversion from NonEmptyMap
to Map
.
*
*
* One use case for this implicit conversion is to enable GenSeq[NonEmptyMap]
s to be flattened.
* Here's an example:
*
*
*
* scala> Vector(NonEmptyMap(1, 2, 3), NonEmptyMap(3, 4), NonEmptyMap(5, 6, 7, 8)).flatten
* res0: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 3, 4, 5, 6, 7, 8)
*
*
* @tparam K the type of the key contained in the NonEmptyMap
* @tparam V the type of the value contained in the NonEmptyMap
* @param nonEmptyMap the NonEmptyMap
to convert to a Map
* @return a Map
containing the elements, in order, of this NonEmptyMap
*/
implicit def nonEmptyMapToMap[K, V](nonEmptyMap: NonEmptyMap[K, V]): scala.collection.immutable.Map[K, V] = nonEmptyMap.toMap
}