izumi.fundamentals.collections.nonempty.NEString.scala Maven / Gradle / Ivy
package izumi.fundamentals.collections.nonempty
// shameless copypaste from Scalactic
import scala.collection.compat.Factory
import scala.collection.mutable.{ArrayBuffer, Buffer}
import scala.collection.{Iterable, Seq}
import scala.language.implicitConversions
import scala.reflect.ClassTag
import scala.collection.compat.*
// Can't be a LinearSeq[T] because Builder would be able to create an empty one.
/**
* A non-empty list: an ordered, immutable, non-empty collection of elements with LinearSeq
performance characteristics.
*
*
* The purpose of NEString
is to allow you to express in a type that a String
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 NEString
s
*
*
* You can construct a NEString
by passing one or more elements to the NEString.apply
factory method:
*
*
*
* scala> NEString(1, 2, 3)
* res0: org.scalactic.anyvals.NEString[Int] = NEString(1, 2, 3)
*
*
*
* Alternatively you can cons elements onto the End
singleton object, similar to making a String
starting with Nil
:
*
*
*
* scala> 1 :: 2 :: 3 :: Nil
* res0: String[Int] = String(1, 2, 3)
*
* scala> 1 :: 2 :: 3 :: End
* res1: org.scalactic.NEString[Int] = NEString(1, 2, 3)
*
*
*
* Note that although Nil
is a String[Nothing]
, End
is
* not a NEString[Nothing]
, because no empty NEString
exists. (A non-empty list is a series
* of connected links; if you have no links, you have no non-empty list.)
*
*
*
* scala> val nil: String[Nothing] = Nil
* nil: String[Nothing] = String()
*
* scala> val nada: NEString[Nothing] = End
* <console>:16: error: type mismatch;
* found : org.scalactic.anyvals.End.type
* required: org.scalactic.anyvals.NEString[Nothing]
* val nada: NEString[Nothing] = End
* ^
*
*
* Working with NEString
s
*
*
* NEString
does not extend Scala's Seq
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> String(1).tail
* res6: String[Int] = String()
*
*
*
* On the other hand, many useful methods exist on Seq
that when invoked on a non-empty Seq
are guaranteed
* to not result in an empty Seq
. For convenience, NEString
defines a method corresponding to every such Seq
* method. Here are some examples:
*
*
*
* NEString(1, 2, 3).map(_ + 1) // Result: NEString(2, 3, 4)
* NEString(1).map(_ + 1) // Result: NEString(2)
* NEString(1, 2, 3).containsSlice(NEString(2, 3)) // Result: true
* NEString(1, 2, 3).containsSlice(NEString(3, 4)) // Result: false
* NEString(-1, -2, 3, 4, 5).minBy(_.abs) // Result: -1
*
*
*
* NEString
does not currently define any methods corresponding to Seq
methods that could result in
* an empty Seq
. However, an implicit converison from NEString
to String
* is defined in the NEString
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 NEString
, even though filter
could result
* in an empty sequence—but the result type will be String
instead of NEString
:
*
*
*
* NEString(1, 2, 3).filter(_ < 10) // Result: String(1, 2, 3)
* NEString(1, 2, 3).filter(_ > 10) // Result: String()
*
*
*
* You can use NEString
s in for
expressions. The result will be an NEString
unless
* you use a filter (an if
clause). Because filters are desugared to invocations of filter
, the
* result type will switch to a String
at that point. Here are some examples:
*
*
*
* scala> import org.scalactic.anyvals._
* import org.scalactic.anyvals._
*
* scala> for (i <- NEString(1, 2, 3)) yield i + 1
* res0: org.scalactic.anyvals.NEString[Int] = NEString(2, 3, 4)
*
* scala> for (i <- NEString(1, 2, 3) if i < 10) yield i + 1
* res1: String[Int] = String(2, 3, 4)
*
* scala> for {
* | i <- NEString(1, 2, 3)
* | j <- NEString('a', 'b', 'c')
* | } yield (i, j)
* res3: org.scalactic.anyvals.NEString[(Int, Char)] =
* NEString((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), (3,a), (3,b), (3,c))
*
* scala> for {
* | i <- NEString(1, 2, 3) if i < 10
* | j <- NEString('a', 'b', 'c')
* | } yield (i, j)
* res6: String[(Int, Char)] =
* String((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), (3,a), (3,b), (3,c))
*
*/
final class NEString private (val theString: String) extends AnyVal {
/**
* Returns a new NEString
containing this NEString
followed by the passed NEString
.
*
* @param other the NEString
to append
* @return a new NEString
that contains this NEString
followed by other
.
*/
def ++(other: NEString): NEString = new NEString(theString ++ other.theString)
/**
* Returns a new NEString
containing this NEString
followed by the characters of the passed Vector
.
*
* @param other the Vector
of Char
to append
* @return a new NEString
that contains this NEString
followed by all characters of other
.
*/
def ++(other: Vector[Char]): NEString = new NEString(theString ++ other.mkString)
// TODO: Have I added these extra ++, etc. methods to Vector that take a NEString?
/**
* Returns a new NEString
containing this NEString
followed by the characters of the passed TraversableOnce
.
*
* @param other the TraversableOnce
of Char
to append
* @return a new NEString
that contains this NEString
followed by all characters of other
.
*/
def ++(other: IterableOnce[Char]): NEString =
if (other.iterator.isEmpty) this else new NEString(theString ++ other.iterator.mkString)
/**
* Returns a new NEString
with the given character prepended.
*
*
* Note that :-ending operators are right associative. A mnemonic for +:
vs. :+
is: the COLon goes on the COLlection side.
*
*
* @param c the character to prepend to this NEString
* @return a new NEString
consisting of c
followed by all characters of this NEString
.
*/
def +:(c: Char): NEString = new NEString(c +: theString)
/**
* Returns a new NEString
with the given character appended.
*
*
* Note a mnemonic for +:
vs. :+
is: the COLon goes on the COLlection side.
*
*
* @param c the character to append to this NEString
* @return a new NEString
consisting of all characters of this NEString
followed by the given c
.
*/
def :+(c: Char): NEString = new NEString(theString :+ c)
/**
* Appends all characters of this NEString
to a string builder. The written text will consist of a concatenation of the result of invoking toString
* on of every element of this NEString
, without any separator string.
*
* @param sb the string builder to which characters will be appended
* @return the string builder, sb
, to which elements were appended.
*/
def addString(sb: StringBuilder): StringBuilder = theString.addString(sb)
/**
* Appends all characters of this NEString
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 character of this NEString
, separated by the string sep
.
*
* @param sb the string builder to which characters will be appended
* @param sep the separator string
* @return the string builder, sb
, to which characters were appended.
*/
def addString(sb: StringBuilder, sep: String): StringBuilder = theString.addString(sb, sep)
/**
* Appends all characters of this NEString
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 characters of this NEString
,
* separated by the string sep
; and the string end
*
* @param sb the string builder to which characters will be appended
* @param start the starting string
* @param sep the separator string
* @param end the ending string
* @return the string builder, sb
, to which characters were appended.
*/
def addString(sb: StringBuilder, start: String, sep: String, end: String): StringBuilder = theString.addString(sb, start, sep, end)
/**
* Selects a character by its index in the NEString
.
*
* @return the character of this NEString
at index idx
, where 0 indicates the first element.
*/
def apply(idx: Int): Char = theString(idx)
/**
* Gets a character by its index in the NEString
.
*
* @return the character of this NEString
at index idx
, where 0 indicates the first element.
*/
def charAt(idx: Int): Char = theString.charAt(idx)
/**
* Finds the first character of this NEString
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 character for which it is defined, or None
if
* the partial function was not defined for any character.
*/
def collectFirst[U](pf: PartialFunction[Char, U]): Option[U] = theString.collectFirst(pf)
/**
* Indicates whether this NEString
contains a given value as an character.
*
* @param c the element to look for
* @return true if this NEString
has an character that is equal (as determined by ==)
to c
, false otherwise.
*/
infix def contains(c: Char): Boolean = theString.contains(c)
/**
* Indicates whether this NEString
contains a given Seq
of characters as a slice.
*
* @param that the Seq
character slice to look for
* @return true if this NEString
contains a slice with the same characters as that
, otherwise false
.
*/
def containsSlice(that: Seq[Char]): Boolean = theString.containsSlice(that)
/**
* Indicates whether this NEString
contains a given Vector
of character as a slice.
*
* @param that the Vector
character slice to look for
* @return true if this NEString
contains a character slice with the same characters as that
, otherwise false
.
*/
def containsSlice(that: Vector[Char]): Boolean = theString.containsSlice(that)
/**
* Indicates whether this NEString
contains a given NEString
as a slice.
*
* @param that the NEString
slice to look for
* @return true if this NEString
contains a slice with the same characters as that
, otherwise false
.
*/
def containsSlice(that: NEString): Boolean = theString.containsSlice(that.theString)
/**
* Copies characters of this NEString
to an array. Fills the given array arr
with characters of this NEString
. Copying
* will stop once either the end of the current NEString
is reached, or the end of the array is reached.
*
* @param arr the array to fill
*/
def copyToArray(arr: Array[Char]): Unit = {
theString.copyToArray(arr, 0)
()
}
/**
* Copies characters of this NEString
to an array. Fills the given array arr
with characters of this NEString
, beginning at
* index start
. Copying will stop once either the end of the current NEString
is reached, or the end of the array is reached.
*
* @param arr the array to fill
* @param start the starting index
*/
def copyToArray(arr: Array[Char], start: Int): Unit = {
theString.copyToArray(arr, start)
()
}
/**
* Copies characters of this NEString
to an array. Fills the given array arr
with at most len
characters of this NEString
, beginning at
* index start
. Copying will stop once either the end of the current NEString
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(arr: Array[Char], start: Int, len: Int): Unit = {
theString.copyToArray(arr, start, len)
()
}
/**
* Copies all characters of this NEString
to a buffer.
*
* @param buf the buffer to which characters are copied
*/
def copyToBuffer(buf: Buffer[Char]): Unit = {
buf ++= theString
()
}
/**
* Indicates whether every character of this NEString
relates to the corresponding element of a given Seq
by satisfying a given predicate.
*
* @tparam B the type of the elements of that
* @param that the Seq
to compare for correspondence
* @param p the predicate, which relates elements from this NEString
and the passed Seq
* @return true if this NEString
and the passed Seq
have the same length and p(x, y)
is true
* for all corresponding elements x
of this NEString
and y
of that, otherwise false
.
*/
def corresponds[B](that: Seq[B])(p: (Char, B) => Boolean): Boolean = theString.corresponds(that)(p)
/**
* Indicates whether every character of this NEString
relates to the corresponding element of a given Vector
by satisfying a given predicate.
*
* @tparam B the type of the elements of that
* @param that the Vector
to compare for correspondence
* @param p the predicate, which relates elements from this NEString
and the passed Vector
* @return true if this NEString
and the passed Vector
have the same length and p(x, y)
is true
* for all corresponding elements x
of this NEString
and y
of that, otherwise false
.
*/
def corresponds[B](that: Vector[B])(p: (Char, B) => Boolean): Boolean = theString.corresponds(that)(p)
/**
* Indicates whether every character of this NEString
relates to the corresponding character of a given NEString
by satisfying a given predicate.
*
* @param that the NEString
to compare for correspondence
* @param p the predicate, which relates elements from this and the passed NEString
* @return true if this and the passed NEString
have the same length and p(x, y)
is true
* for all corresponding characters x
of this NEString
and y
of that, otherwise false
.
*/
def corresponds(that: NEString)(p: (Char, Char) => Boolean): Boolean = theString.corresponds(that.theString)(p)
/**
* Counts the number of characters in this NEString
that satisfy a predicate.
*
* @param p the predicate used to test characters.
* @return the number of characters satisfying the predicate p
.
*/
def count(p: Char => Boolean): Int = theString.count(p)
/**
* Builds a new NEString
from this NEString
without any duplicate characters.
*
* @return A new NEString
that contains the first occurrence of every character of this NEString
.
*/
def distinct: NEString = new NEString(theString.iterator.toSeq.distinct.mkString)
/**
* Indicates whether this NEString
ends with the given Seq
of Char.
*
* @param that the sequence to test
* @return true
if this NEString
has that
as a suffix, false
otherwise.
*/
def endsWith[B](that: Seq[B]): Boolean = theString.toSeq.endsWith[Any](that)
/**
* Indicates whether this NEString
ends with the given Vector
.
*
* @param that the Vector
to test
* @return true
if this NEString
has that
as a suffix, false
otherwise.
*/
def endsWith[B](that: Vector[B]): Boolean = theString.toSeq.endsWith[Any](that)
// TODO: Search for that: Vector in here and add a that: NEString in Vector.
/**
* Indicates whether this NEString
ends with the given NEString
.
*
* @param that the NEString
to test
* @return true
if this NEString
has that
as a suffix, false
otherwise.
*/
def endsWith(that: NEString): Boolean = theString.toSeq.endsWith[Any](that.theString)
/*
override def equals(o: Any): Boolean =
o match {
case NEString: NEString[?] => toString == NEString.toString
case _ => false
}
*/
/**
* Indicates whether a predicate holds for at least one of the characters of this NEString
.
*
* @param p the predicate used to test characters.
* @return true
if the given predicate p
holds for some of the elements of this NEString
, otherwise false
.
*/
def exists(p: Char => Boolean): Boolean = theString.exists(p)
/**
* Finds the first character of this NEString
that satisfies the given predicate, if any.
*
* @param p the predicate used to test characters
* @return an Some
containing the first character in this NEString
that satisfies p
, or None
if none exists.
*/
def find(p: Char => Boolean): Option[Char] = theString.find(p)
/**
* Builds a new NEString
by applying a function to all characters of this NEString
and using the characters of the resulting NEString
s.
*
* @param f the function to apply to each character.
* @return a new NEString
containing characters obtained by applying the given function f
to each character of this NEString
and concatenating
* the characters of resulting NEString
s.
*/
def flatMap(f: Char => NEString): NEString = {
val buf = new ArrayBuffer[Char]
for (c <- theString)
buf ++= f(c).theString
new NEString(buf.mkString)
}
/**
* Folds the characters of this NEString
using the specified associative binary operator.
*
*
* The order in which operations are performed on characters is unspecified and may be nondeterministic.
*
*
* @param z a neutral character 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(z: Char)(op: (Char, Char) => Char): Char = theString.fold(z)(op)
/**
* Applies a binary operator to a start value and all characters of this NEString
, 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 characters of this NEString
, 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 NEString
.
*
*/
def foldLeft[B](z: B)(op: (B, Char) => B): B = theString.foldLeft(z)(op)
/**
* Applies a binary operator to all characters of this NEString
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 characters of this NEString
, 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 NEString
.
*
*/
def foldRight[B](z: B)(op: (Char, B) => B): B = theString.foldRight(z)(op)
/**
* Indicates whether a predicate holds for all characters of this NEString
.
*
* @param p the predicate used to test characters.
* @return true
if the given predicate p
holds for all characters of this NEString
, otherwise false
.
*/
def forall(p: Char => Boolean): Boolean = theString.forall(p)
/**
* Applies a function f
to all characters of this NEString
.
*
* @param f the function that is applied for its side-effect to every character. The result of function f
is discarded.
*/
def foreach(f: Char => Unit): Unit = theString.foreach(f)
/**
* Partitions this NEString
into a map of NEString
s according to some discriminator function.
*
* @tparam K the type of keys returned by the discriminator function.
* @param f the discriminator function.
* @return A map from keys to NEString
s such that the following invariant holds:
*
*
* (NEString.toString partition f)(k) = xs filter (x => f(x) == k)
*
*
*
* That is, every key k
is bound to a NEString
of those elements x
for which f(x)
equals k
.
*
*/
def groupBy[K](f: Char => K): Map[K, NEString] = {
val mapKToString = theString.iterator.toSeq.groupBy(f)
mapKToString.view.mapValues {
list => new NEString(list.mkString)
}.toMap
}
/**
* Partitions characters into fixed size NEString
s.
*
* @param size the number of characters per group
* @return An iterator producing NEString
s of size size
, except the last will be truncated if the characters don't divide evenly.
*/
def grouped(size: Int): Iterator[NEString] = {
if (size > 0) {
val itOfString = theString.grouped(size)
itOfString.map {
list => new NEString(list)
}
} else
throw new IllegalArgumentException(s"Invalid size: $size")
}
/**
* Returns true
to indicate this NEString
has a definite size, since all NEString
s are strict collections.
*/
def hasDefiniteSize: Boolean = true
// override def hashCode: Int = toString.hashCode
/**
* Selects the first character of this NEString
.
*
* @return the first character of this NEString
.
*/
def head: Char = theString.head
def tail: String = theString.tail
/**
* Finds index of first occurrence of some value in this NEString
.
*
* @param c the character value to search for.
* @return the index of the first character of this NEString
that is equal (as determined by ==
) to c
,
* or -1
, if none exists.
*/
def indexOf(c: Char): Int = theString.indexOf(c.toInt, 0)
/**
* Finds index of first occurrence of some value in this NEString
after or at some start index.
*
* @param c the character value to search for.
* @param from the start index
* @return the index >=
from
of the first element of this NEString
that is equal (as determined by ==
) to elem
,
* or -1
, if none exists.
*/
def indexOf(c: Char, from: Int): Int = theString.indexOf(c.toInt, from)
/**
* Finds first index where this NEString
contains a given Seq[Char]
as a slice.
*
* @param that the Seq[Char]
defining the slice to look for
* @return the first index at which the elements of this NEString
starting at that index match the characters of
* Seq
that
, or -1
of no such subsequence exists.
*/
def indexOfSlice(that: Seq[Char]): Int = theString.indexOfSlice(that)
/**
* Finds first index after or at a start index where this NEString
contains a given Seq[Char]
as a slice.
*
* @param that the Seq[Char]
defining the slice to look for
* @param from the start index
* @return the first index >=
from
at which the characters of this NEString
starting at that index match the characters of
* Seq[Char]
that
, or -1
of no such subsequence exists.
*/
def indexOfSlice(that: Seq[Char], from: Int): Int = theString.indexOfSlice(that, from)
/**
* Finds first index where this NEString
contains a given Vector
as a slice.
*
* @param that the Vector
defining the slice to look for
* @return the first index such that the characters of this NEString
starting at this index match the characters of
* Vector
that
, or -1
of no such subsequence exists.
*/
def indexOfSlice(that: Vector[Char]): Int = theString.indexOfSlice(that)
/**
* Finds first index where this NEString
contains a given NEString
as a slice.
*
* @param that the NEString
defining the slice to look for
* @return the first index such that the characters of this NEString
starting at this index match the characters of
* NEString
that
, or -1
of no such subsequence exists.
*/
def indexOfSlice(that: NEString): Int = theString.indexOfSlice(that.theString)
/**
* Finds first index after or at a start index where this NEString
contains a given Vector
as a slice.
*
* @param that the Vector
defining the slice to look for
* @param from the start index
* @return the first index >=
from
such that the characters of this NEString
starting at this index match the characters of
* Vector
that
, or -1
of no such subsequence exists.
*/
def indexOfSlice(that: Vector[Char], from: Int): Int = theString.indexOfSlice(that, from)
/**
* Finds first index after or at a start index where this NEString
contains a given NEString
as a slice.
*
* @param that the NEString
defining the slice to look for
* @param from the start index
* @return the first index >=
from
such that the characters of this NEString
starting at this index match the characters of
* NEString
that
, or -1
of no such subsequence exists.
*/
def indexOfSlice(that: NEString, from: Int): Int = theString.indexOfSlice(that.theString, from)
/**
* Finds index of the first character satisfying some predicate.
*
* @param p the predicate used to test characters.
* @return the index of the first character of this NEString
that satisfies the predicate p
,
* or -1
, if none exists.
*/
def indexWhere(p: Char => Boolean): Int = theString.indexWhere(p)
/**
* Finds index of the first character satisfying some predicate after or at some start index.
*
* @param p the predicate used to test characters.
* @param from the start index
* @return the index >=
from
of the first character of this NEString
that satisfies the predicate p
,
* or -1
, if none exists.
*/
def indexWhere(p: Char => Boolean, from: Int): Int = theString.indexWhere(p, from)
/**
* Produces the range of all indices of this NEString
.
*
* @return a Range
value from 0
to one less than the length of this NEString
.
*/
def indices: Range = theString.indices
/**
* Tests whether this NEString
contains given index.
*
* @param idx the index to test
* @return true if this NEString
contains an character at position idx
, false
otherwise.
*/
def isDefinedAt(idx: Int): Boolean = theString.isDefinedAt(idx)
/**
* Returns false
to indicate this NEString
, like all NEString
s, is non-empty.
*
* @return false
*/
def isEmpty: Boolean = false
/**
* Returns true
to indicate this NEString
, like all NEString
s, can be traversed repeatedly.
*
* @return true
*/
def isTraversableAgain: Boolean = true
/**
* Creates and returns a new iterator over all characters contained in this NEString
.
*
* @return the new iterator
*/
def iterator: Iterator[Char] = theString.iterator
/**
* Selects the last character of this NEString
.
*
* @return the last character of this NEString
.
*/
def last: Char = theString.last
/**
* Finds the index of the last occurrence of some value in this NEString
.
*
* @param c the character value to search for.
* @return the index of the last character of this NEString
that is equal (as determined by ==
) to c
,
* or -1
, if none exists.
*/
def lastIndexOf(c: Char): Int = theString.lastIndexOf(c.toInt)
/**
* Finds the index of the last occurrence of some value in this NEString
before or at a given end
index.
*
* @param c the character value to search for.
* @param end the end index.
* @return the index >=
end
of the last character of this NEString
that is equal (as determined by ==
)
* to elem
, or -1
, if none exists.
*/
def lastIndexOf(c: Char, end: Int): Int = theString.lastIndexOf(c.toInt, end)
/**
* Finds the last index where this NEString
contains a given Seq
as a slice.
*
* @param that the Seq
defining the slice to look for
* @return the last index at which the elements of this NEString
starting at that index match the characters of
* Seq
that
, or -1
of no such subsequence exists.
*/
def lastIndexOfSlice(that: Seq[Char]): Int = theString.lastIndexOfSlice(that)
/**
* Finds the last index before or at a given end index where this NEString
contains a given Seq
as a slice.
*
* @param that the Seq
defining the slice to look for
* @param end the end index
* @return the last index >=
end
at which the elements of this NEString
starting at that index match the characters of
* Seq
that
, or -1
of no such subsequence exists.
*/
def lastIndexOfSlice(that: Seq[Char], end: Int): Int = theString.lastIndexOfSlice(that, end)
/**
* Finds the last index where this NEString
contains a given Vector
as a slice.
*
* @param that the Vector
defining the slice to look for
* @return the last index at which the elements of this NEString
starting at that index match the characters of
* Vector
that
, or -1
of no such subsequence exists.
*/
def lastIndexOfSlice(that: Vector[Char]): Int = theString.lastIndexOfSlice(that)
/**
* Finds the last index where this NEString
contains a given NEString
as a slice.
*
* @param that the NEString
defining the slice to look for
* @return the last index at which the elements of this NEString
starting at that index match the characters of
* NEString
that
, or -1
of no such subsequence exists.
*/
def lastIndexOfSlice(that: NEString): Int = theString.lastIndexOfSlice(that.theString)
/**
* Finds the last index before or at a given end index where this NEString
contains a given Vector
as a slice.
*
* @param that the Vector
defining the slice to look for
* @param end the end index
* @return the last index >=
end
at which the elements of this NEString
starting at that index match the characters of
* Vector
that
, or -1
of no such subsequence exists.
*/
def lastIndexOfSlice(that: Vector[Char], end: Int): Int = theString.lastIndexOfSlice(that, end)
/**
* Finds the last index before or at a given end index where this NEString
contains a given NEString
as a slice.
*
* @param that the NEString
defining the slice to look for
* @param end the end index
* @return the last index >=
end
at which the characters of this NEString
starting at that index match the characters of
* NEString
that
, or -1
of no such subsequence exists.
*/
def lastIndexOfSlice(that: NEString, end: Int): Int = theString.lastIndexOfSlice(that.theString, end)
/**
* Finds index of last character satisfying some predicate.
*
* @param p the predicate used to test characters.
* @return the index of the last character of this NEString
that satisfies the predicate p
, or -1
, if none exists.
*/
def lastIndexWhere(p: Char => Boolean): Int = theString.lastIndexWhere(p)
/**
* Finds index of last character satisfying some predicate before or at given end index.
*
* @param p the predicate used to test characters.
* @param end the end index
* @return the index >=
end
of the last character of this NEString
that satisfies the predicate p
,
* or -1
, if none exists.
*/
def lastIndexWhere(p: Char => Boolean, end: Int): Int = theString.lastIndexWhere(p, end)
/**
* The length of this NEString
.
*
*
* @note length
and size
yield the same result, which will be >
= 1.
*
*
* @return the number of characters in this NEString
.
*/
def length: Int = theString.length
/**
* Compares the length of this NEString
to a test value.
*
* @param len the test value that gets compared with the length.
* @return a value x
where
*
*
* x < 0 if this.length < len
* x == 0 if this.length == len
* x > 0 if this.length > len
*
*/
def lengthCompare(len: Int): Int = theString.lengthCompare(len)
/**
* Builds a new NEString
by applying a function to all characters of this NEString
.
*
* @tparam U the character type of the returned NEString
.
* @param f the function to apply to each character.
* @return a new NEString
resulting from applying the given function f
to each character of this NEString
and collecting the results.
*/
def map[U](f: Char => U): NEString = {
// NEString("test")
new NEString(
theString.map {
c =>
f(c).toString
}.mkString
)
}
/**
* Finds the largest character.
*
* @return the largest element of this NEString
.
*/
def max(implicit cmp: Ordering[Char]): Char = theString.max(cmp)
/**
* Finds the largest result after applying the given function to every character.
*
* @return the largest result of applying the given function to every character of this NEString
.
*/
def maxBy[U](f: Char => U)(implicit cmp: Ordering[U]): Char = theString.maxBy(f)(cmp)
/**
* Finds the smallest character.
*
* @return the smallest character of this NEString
.
*/
def min(implicit cmp: Ordering[Char]): Char = theString.min(cmp)
/**
* Finds the smallest result after applying the given function to every character.
*
* @return the smallest result of applying the given function to every character of this NEString
.
*/
def minBy[U](f: Char => U)(implicit cmp: Ordering[U]): Char = theString.minBy(f)(cmp)
/**
* Displays all characters of this NEString
in a string.
*
* @return a string representation of this NEString
. In the resulting string, the result of invoking toString
on all characters of this
* NEString
follow each other without any separator string.
*/
def mkString: String = theString.mkString
/**
* Displays all elements of this NEString
in a string using a separator string.
*
* @param sep the separator string
* @return a string representation of this NEString
. In the resulting string, the result of invoking toString
on all elements of this
* NEString
are separated by the string sep
.
*/
def mkString(sep: String): String = theString.mkString(sep)
/**
* Displays all characters of this NEString
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 NEString
. 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 characters of this NEString
are
* separated by the string sep
.
*/
def mkString(start: String, sep: String, end: String): String = theString.mkString(start, sep, end)
/**
* Returns true
to indicate this NEString
, like all NEString
s, is non-empty.
*
* @return true
*/
def nonEmpty: Boolean = true
/**
* A copy of this NEString
with an element value appended until a given target length is reached.
*
* @param len the target length
* @param c the padding character
* @return a new NEString
consisting of all characters of this NEString
followed by the minimal number of occurrences
* of elem
so that the resulting NEString
has a length of at least len
.
*/
def padTo(len: Int, c: Char): NEString =
new NEString(theString.padTo(len, c))
/**
* Produces a new NEString
where a slice of characters in this NEString
is replaced by another NEString
*
* @param from the index of the first replaced character
* @param that the NEString
whose characters should replace a slice in this NEString
* @param replaced the number of characters to drop in the original NEString
*/
def patch(from: Int, that: NEString, replaced: Int): NEString =
new NEString(theString.patch(from, that.theString, replaced))
/**
* Iterates over distinct permutations.
*
*
* Here's an example:
*
*
*
* NEString("abb").permutations.toList == list(NEString("abb"), NEString("bab"), NEString("bba"))
*
*
* @return an iterator that traverses the distinct permutations of this NEString
.
*/
def permutations: Iterator[NEString] = {
val it = theString.iterator.toSeq.permutations
it map {
list => new NEString(list.mkString)
}
}
/**
* Returns the length of the longest prefix whose characters all satisfy some predicate.
*
* @param p the predicate used to test characters.
* @return the length of the longest prefix of this NEString
such that every characters
* of the segment satisfies the predicate p
.
*/
def prefixLength(p: Char => Boolean): Int = theString.segmentLength(p, 0)
/**
* The result of multiplying all the characters of this NEString
.
*
*
* This method can be invoked for any NEString
for which an implicit Numeric[T]
exists.
*
*
* @return the product of all elements
*/
def product(implicit num: Numeric[Char]): Char = theString.product(num)
/**
* Reduces the elements of this NEString
using the specified associative binary operator.
*
*
* The order in which operations are performed on characters is unspecified and may be nondeterministic.
*
*
* @param op a binary operator that must be associative.
* @return the result of applying reduce operator op
between all the characters of this NEString
.
*/
def reduce(op: (Char, Char) => Char): Char = theString.reduce(op)
/**
* Applies a binary operator to all characters of this NEString
, going left to right.
*
* @param op the binary operator.
* @return the result of inserting op
between consecutive characters of this NEString
, going left to right:
*
*
* op(...op(op(x_1, x_2), x_3), ..., x_n)
*
*
*
* where x1, ..., xn are the characters of this NEString
.
*
*/
def reduceLeft(op: (Char, Char) => Char): Char = theString.reduceLeft(op)
/**
* Applies a binary operator to all characters of this NEString
, going left to right, returning the result in a Some
.
*
* @param op the binary operator.
* @return a Some
containing the result of reduceLeft(op)
*
*/
def reduceLeftOption(op: (Char, Char) => Char): Option[Char] = theString.reduceLeftOption(op)
def reduceOption(op: (Char, Char) => Char): Option[Char] = theString.reduceOption(op)
/**
* Applies a binary operator to all characters of this NEString
, going right to left.
*
* @param op the binary operator
* @return the result of inserting op
between consecutive characters of this NEString
, going right to left:
*
*
* op(x_1, op(x_2, ... op(x_{n-1}, x_n)...))
*
*
*
* where x1, ..., xn are the elements of this NEString
.
*
*/
def reduceRight(op: (Char, Char) => Char): Char = theString.reduceRight(op)
/**
* Applies a binary operator to all elements of this NEString
, going right to left, returning the result in a Some
.
*
* @param op the binary operator
* @return a Some
containing the result of reduceRight(op)
*/
def reduceRightOption(op: (Char, Char) => Char): Option[Char] = theString.reduceRightOption(op)
/**
* Returns new NEString
with characters in reverse order.
*
* @return a new NEString
with all characters of this NEString
in reversed order.
*/
def reverse: NEString =
new NEString(theString.reverse)
/**
* An iterator yielding characters in reverse order.
*
*
* @note NEString.reverseIterator
is the same as NEString.reverse.iterator
, but might be more efficient.
*
*
* @return an iterator yielding the characters of this NEString
in reversed order
*/
def reverseIterator: Iterator[Char] = theString.reverseIterator
/**
* Builds a new Iterable
by applying a function to all characters of this NEString
and collecting the results in reverse order.
*
*
* @note NEString.reverseMap(f)
is the same as NEString.reverse.map(f)
, but might be more efficient.
*
*
* @tparam U the element type of the returned Iterable
.
* @param f the function to apply to each character.
* @return a new Iterable
resulting from applying the given function f
to each character of this NEString
* and collecting the results in reverse order.
*/
def reverseMap[U](f: Char => U): Iterable[U] = theString.reverseIterator.map(f).toVector
/**
* Checks if the given Iterable
contains the same characters in the same order as this NEString
.
*
* @param that the Iterable
with which to compare
* @return true
, if both this NEString
and the given Iterable
contain the same characters
* in the same order, false
otherwise.
*/
def sameElements(that: Iterable[Char]): Boolean = theString.sameElements(that)
/**
* Checks if the given Vector
contains the same characters in the same order as this NEString
.
*
* @param that the Vector
with which to compare
* @return true
, if both this and the given Vector
contain the same characters
* in the same order, false
otherwise.
*/
def sameElements(that: Vector[Char]): Boolean = theString.sameElements(that)
/**
* Checks if the given NEString
contains the same characters in the same order as this NEString
.
*
* @param that the NEString
with which to compare
* @return true
, if both this and the given NEString
contain the same characters
* in the same order, false
otherwise.
*/
def sameElements(that: NEString): Boolean = theString.sameElements(that.theString)
/**
* Computes a prefix scan of the characters of this NEString
.
*
*
* @note The neutral character z may be applied more than once.
*
*
*
* Here are some examples:
*
*
*
* NEString("123").scan(0)(_ + _) == NEString(0, 1, 3, 6)
* NEString("123").scan("z")(_ + _.toString) == NEString("z", "z1", "z12", "z123")
*
*
* @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 NEString
containing the prefix scan of the elements in this NEString
*/
def scan(z: Char)(op: (Char, Char) => Char): NEString = new NEString(theString.scan(z)(op).mkString)
/**
* Produces a NEString
containing cumulative results of applying the operator going left to right.
*
*
* Here are some examples:
*
*
*
* NEString("123").scanLeft(0)(_ + _.toString.toInt) == Vector(0, 1, 3, 6)
* NEString("123").scanLeft("z")(_ + _) == Vector("z", "z1", "z12", "z123")
*
*
* @tparam B the result type of the binary operator and type of the resulting NEString
* @param z the start value.
* @param op the binary operator.
* @return a new NEString
containing the intermediate results of inserting op
between consecutive characters of this NEString
,
* going left to right, with the start value, z
, on the left.
*/
def scanLeft[B](z: B)(op: (B, Char) => B): Iterable[B] = theString.scanLeft(z)(op)
/**
* Produces a NEString
containing cumulative results of applying the operator going right to left.
*
*
* Here are some examples:
*
*
*
* NEString("123").scanRight(0)(_.toString.toInt + _) == NEString(6, 5, 3, 0)
* NEString("123").scanRight("z")(_ + _) == NEString("123z", "23z", "3z", "z")
*
*
* @tparam B the result of the binary operator and type of the resulting NEString
* @param z the start value
* @param op the binary operator
* @return a new NEString
containing the intermediate results of inserting op
between consecutive characters of this NEString
,
* going right to left, with the start value, z
, on the right.
*/
def scanRight[B](z: B)(op: (Char, B) => B): Iterable[B] = theString.scanRight(z)(op)
/**
* Computes length of longest segment whose characters all satisfy some predicate.
*
* @param p the predicate used to test elements.
* @param from the index where the search starts.
* @return the length of the longest segment of this NEString
starting from index from
such that every character of the
* segment satisfies the predicate p
.
*/
def segmentLength(p: Char => Boolean, from: Int): Int = theString.segmentLength(p, from)
/**
* Groups characters 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 characters per group
* @return an iterator producing NEString
s of size size
, except the last and the only element will be truncated
* if there are fewer characters than size
.
*/
def sliding(size: Int): Iterator[NEString] = theString.iterator.sliding(size).map(s => new NEString(s.mkString))
/**
* Groups characters 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 characters per group
* @param step the distance between the first characters of successive groups
* @return an iterator producing NEString
s of size size
, except the last and the only character will be truncated
* if there are fewer characters than size
.
*/
def sliding(size: Int, step: Int): Iterator[NEString] = theString.iterator.sliding(size, step).map(s => new NEString(s.mkString))
/**
* The size of this NEString
.
*
*
* @note length
and size
yield the same result, which will be >
= 1.
*
*
* @return the number of characters in this NEString
.
*/
def size: Int = theString.size
/**
* Sorts this NEString
according to the Ordering
of the result of applying the given function to every character.
*
* @tparam U the target type of the transformation f
, and the type where the Ordering
ord
is defined.
* @param f the transformation function mapping elements to some other domain U
.
* @param ord the ordering assumed on domain U
.
* @return a NEString
consisting of the elements of this NEString
sorted according to the Ordering
where
* x < y if ord.lt(f(x), f(y))
.
*/
def sortBy[U](f: Char => U)(implicit ord: Ordering[U]): NEString = new NEString(theString.iterator.toSeq.sortBy(f).mkString)
/**
* Sorts this NEString
according to a comparison function.
*
*
* The sort is stable. That is, characters that are equal (as determined by lt
) appear in the same order in the
* sorted NEString
as in the original.
*
*
* @param lt the comparison function that tests whether its first argument precedes its second argument in the desired ordering.
* @return a NEString
consisting of the elements of this NEString
sorted according to the comparison function lt
.
*/
def sortWith(lt: (Char, Char) => Boolean): NEString = new NEString(theString.iterator.toSeq.sortWith(lt).mkString)
/**
* Sorts this NEString
according to an Ordering
.
*
*
* The sort is stable. That is, elements that are equal (as determined by lt
) appear in the same order in the
* sorted NEString
as in the original.
*
*
* @param ord the Ordering
to be used to compare elements.
* @return a NEString
consisting of the characters of this NEString
sorted according to the ordering defined by ord
.
*/
def sorted(implicit ord: Ordering[Char]): NEString = new NEString(theString.iterator.toSeq.sorted(ord).mkString)
/**
* Indicates whether this NEString
starts with the given Seq
.
*
* @param that the Seq
slice to look for in this NEString
* @return true
if this NEString
has that
as a prefix, false
otherwise.
*/
def startsWith(that: Seq[Char]): Boolean = wrapString(theString).startsWith(that)
/**
* Indicates whether this NEString
starts with the given Seq
at the given index.
*
* @param that the Seq
slice to look for in this NEString
* @param offset the index at which this NEString
is searched.
* @return true
if this NEString
has that
as a slice at the index offset
, false
otherwise.
*/
def startsWith(that: Seq[Char], offset: Int): Boolean = wrapString(theString).startsWith(that, offset)
/**
* Indicates whether this NEString
starts with the given Vector
.
*
* @param that the Vector
to test
* @return true
if this collection has that
as a prefix, false
otherwise.
*/
def startsWith(that: Vector[Char]): Boolean = wrapString(theString).startsWith(that)
/**
* Indicates whether this NEString
starts with the given NEString
.
*
* @param that the NEString
to test
* @return true
if this collection has that
as a prefix, false
otherwise.
*/
def startsWith(that: NEString): Boolean = theString.startsWith(that.theString)
/**
* Indicates whether this NEString
starts with the given Vector
at the given index.
*
* @param that the Vector
slice to look for in this NEString
* @param offset the index at which this NEString
is searched.
* @return true
if this NEString
has that
as a slice at the index offset
, false
otherwise.
*/
def startsWith(that: Vector[Char], offset: Int): Boolean = wrapString(theString).startsWith(that, offset)
/**
* Indicates whether this NEString
starts with the given NEString
at the given index.
*
* @param that the NEString
slice to look for in this NEString
* @param offset the index at which this NEString
is searched.
* @return true
if this NEString
has that
as a slice at the index offset
, false
otherwise.
*/
def startsWith(that: NEString, offset: Int): Boolean = theString.startsWith(that.theString, offset)
/**
* Returns "NEString"
, the prefix of this object's toString
representation.
*
* @return the string "NEString"
*/
def stringPrefix: String = "NEString"
/**
* The result of summing all the characters of this NEString
.
*
*
* This method can be invoked for any NEString
for which an implicit Numeric[Char]
exists.
*
*
* @return the sum of all elements
*/
def sum(implicit num: Numeric[Long]): Long = theString.iterator.map(_.toLong).sum(num)
/**
* Converts this NEString
into a collection of type Col
by copying all elements.
*
* @tparam C1 the collection type to build.
* @return a new collection containing all elements of this NEString
.
*/
def to[C1](factory: Factory[Char, C1]): C1 = factory.fromSpecific(iterator)
/**
* Converts this NEString
to an array.
*
* @return an array containing all characters of this NEString
. A ClassTag
must be available for the element type of this NEString
.
*/
def toArray(implicit classTag: ClassTag[Char]): Array[Char] = theString.toArray
/**
* Converts this NEString
to a Vector
.
*
* @return a Vector
containing all characters of this NEString
.
*/
def toVector: Vector[Char] = theString.toVector
/**
* Converts this NEString
to a mutable buffer.
*
* @return a buffer containing all characters of this NEString
.
*/
def toBuffer: Buffer[Char] = theString.toBuffer
/**
* Converts this NEString
to an immutable IndexedSeq
.
*
* @return an immutable IndexedSeq
containing all characters of this NEString
.
*/
def toIndexedSeq: collection.immutable.IndexedSeq[Char] = theString.toVector
/**
* Converts this NEString
to an iterable collection.
*
* @return an Iterable
containing all characters of this NEString
.
*/
def toIterable: Iterable[Char] = theString
/**
* Returns an Iterator
over the elements in this NEString
.
*
* @return an Iterator
containing all characters of this NEString
.
*/
def toIterator: Iterator[Char] = theString.iterator
/**
* Converts this NEString
to a map.
*
*
* This method is unavailable unless the elements are members of Tuple2
, each ((K, V))
becoming a key-value pair
* in the map. Duplicate keys will be overwritten by later keys.
*
*
* @return a map of type immutable.Map[Int, Char]
containing all index/character pairs of type (Int, Char)
of this NEString
.
*/
def toMap: Map[Int, Char] = Map.empty[Int, Char] ++ theString.zipWithIndex.map(e => e._2 -> e._1)
/**
* Converts this NEString
to an immutable IndexedSeq
.
*
* @return an immutable IndexedSeq
containing all characters of this NEString
.
*/
def toSeq: collection.immutable.Seq[Char] = theString
/**
* Converts this NEString
to a set.
*
* @return a set containing all characters of this NEString
.
*/
def toSet: Set[Char] = theString.toSet
/**
* Returns a string representation of this NEString
.
*
* @return the string "NEString"
followed by the result of invoking toString
on
* this NEString
's elements, surrounded by parentheses.
*/
override def toString: String = stringPrefix + "(" + theString + ")"
/**
* Produces a new NEString
that contains all characters of this NEString
and also all characters of a given Vector
.
*
*
* NEStringX
union
everyY
is equivalent to NEStringX
++
everyY
.
*
*
*
* Another way to express this is that NEStringX
union
everyY
computes the order-presevring multi-set union
* of NEStringX
and everyY
. This union
method is hence a counter-part of diff
and intersect
that
* also work on multi-sets.
*
*
* @param that the Vector
to add.
* @return a new NEString
that contains all characters of this NEString
followed by all characters of that
Vector
.
*/
def union(that: Vector[Char]): NEString = new NEString(theString + that.mkString)
/**
* Produces a new NEString
that contains all characters of this NEString
and also all characters of a given NEString
.
*
*
* NEStringX
union
NEStringY
is equivalent to NEStringX
++
NEStringY
.
*
*
*
* Another way to express this is that NEStringX
union
NEStringY
computes the order-presevring multi-set union
* of NEStringX
and NEStringY
. This union
method is hence a counter-part of diff
and intersect
that
* also work on multi-sets.
*
*
* @param that the NEString
to add.
* @return a new NEString
that contains all elements of this NEString
followed by all characters of that
.
*/
def union(that: NEString): NEString = new NEString(theString + that.theString)
/**
* Produces a new NEString
that contains all characters of this NEString
and also all characters of a given Seq
.
*
*
* NEStringX
union
ys
is equivalent to NEStringX
++
ys
.
*
*
*
* Another way to express this is that NEStringX
union
ys
computes the order-presevring multi-set union
* of NEStringX
and ys
. This union
method is hence a counter-part of diff
and intersect
that
* also work on multi-sets.
*
*
* @param that the Seq
to add.
* @return a new NEString
that contains all elements of this NEString
followed by all elements of that
Seq
.
*/
def union(that: Seq[Char]): NEString = new NEString(theString + that.mkString)
/**
* Converts this NEString
of pairs into two NEString
s of the first and second half of each pair.
*
* @tparam L the type of the first half of the character pairs
* @tparam R the type of the second half of the character pairs
* @param asPair an implicit conversion that asserts that the character type of this NEString
is a pair.
* @return a pair of NEString
s, containing the first and second half, respectively, of each character pair of this NEString
.
*/
def unzip[L, R](implicit asPair: Char => (L, R)): (Iterable[L], Iterable[R]) = {
val unzipped = theString.unzip
(unzipped._1, unzipped._2)
}
/**
* Converts this NEString
of triples into three NEString
s of the first, second, and and third character of each triple.
*
* @tparam L the type of the first member of the character triples
* @tparam R the type of the second member of the character triples
* @tparam R the type of the third member of the character triples
* @param asTriple an implicit conversion that character that the character type of this NEString
is a triple.
* @return a triple of NEString
s, containing the first, second, and third member, respectively, of each character triple of this NEString
.
*/
def unzip3[L, M, R](implicit asTriple: Char => (L, M, R)): (Iterable[L], Iterable[M], Iterable[R]) = {
val unzipped = theString.unzip3
(unzipped._1, unzipped._2, unzipped._3)
}
/**
* A copy of this NEString
with one single replaced character.
*
* @param idx the position of the replacement
* @param c the replacing character
* @throws IndexOutOfBoundsException if the passed index is greater than or equal to the length of this NEString
* @return a copy of this NEString
with the character at position idx
replaced by c
.
*/
def updated(idx: Int, c: Char): NEString =
try new NEString(theString.updated(idx, c))
catch { case _: UnsupportedOperationException => throw new IndexOutOfBoundsException(idx.toString) } // This is needed for 2.10 support. Can drop after.
// Because 2.11 throws IndexOutOfBoundsException.
/**
* Returns a NEString
formed from this NEString
and an iterable collection by combining corresponding
* elements in pairs. If one of the two collections is shorter than the other, placeholder elements will be used to extend the
* shorter collection to the length of the longer.
*
* @tparam O the element type of the other
* @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 NEString
is shorter than that
Iterable
.
* @param otherElem the element to be used to fill up the result if that
Iterable
is shorter than this NEString
.
* @return a new NEString
containing pairs consisting of corresponding characters of this NEString
and that
. The
* length of the returned collection is the maximum of the lengths of this NEString
and that
. If this NEString
* is shorter than that
, thisElem
values are used to pad the result. If that
is shorter than this
* NEString
, thatElem
values are used to pad the result.
*/
def zipAll[O](other: collection.Iterable[O], thisElem: Char, otherElem: O): Iterable[(Char, O)] =
theString.zipAll(other, thisElem, otherElem)
/**
* Returns a NEString
formed from this NEString
and another NEString
combining corresponding
* elements in pairs. If one of the two
is shorter than the other, placeholder elements will be used to extend the
* shorter collection to the length of the longer.
*
* @param other the NEString
providing the second half of each result pair
* @param thisElem the character to be used to fill up the result if this NEString
is shorter than that
NEString
.
* @param otherElem the character to be used to fill up the result if that
Iterable
is shorter than this NEString
.
* @return a new NEString
containing pairs consisting of corresponding characters of this NEString
and that
. The
* length of the returned collection is the maximum of the lengths of this NEString
and that
. If this NEString
* is shorter than that
, thisElem
values are used to pad the result. If that
is shorter than this
* NEString
, thatElem
values are used to pad the result.
*/
def zipAll(other: NEString, thisElem: Char, otherElem: Char): Iterable[(Char, Char)] =
theString.zipAll(other.theString, thisElem, otherElem)
/**
* Zips this NEString
with its indices.
*
* @return A new NEString
containing pairs consisting of all elements of this NEString
paired with their index. Indices start at 0.
*/
def zipWithIndex: Iterable[(Char, Int)] = theString.zipWithIndex
}
/**
* Companion object for class NEString
.
*/
object NEString {
/**
* Constructs a new NEString
given at least one character.
*
* @param firstChar the first character (with index 0) contained in this NEString
* @param otherChars a varargs of zero or more other characters (with index 1, 2, 3, ...) contained in this NEString
*/
@inline def apply(firstChar: Char, otherChars: Char*): NEString = new NEString(firstChar.toString + otherChars.mkString)
/**
* Variable argument extractor for NEString
s.
*
* @param NEString: the NEString
containing the elements to extract
* @return an Seq
containing this NEString
s elements, wrapped in a Some
*/
@inline def unapplySeq(NEString: NEString): Some[Seq[String]] = Some(Seq(NEString.theString))
/**
* Optionally construct a NEString
containing the characters, if any, of a given Seq
.
*
* @param seq the Seq
of Char
with which to construct a NEString
* @return a NEString
containing the elements of the given Seq
, if non-empty, wrapped in
* a Some
; else None
if the Seq
is empty
*/
@inline def from[T](seq: Seq[Char]): Option[NEString] =
seq.headOption match {
case None => None
case Some(_) => Some(new NEString(seq.mkString))
}
@inline def from[T](str: String): Option[NEString] =
if (str.isEmpty) None else Some(new NEString(str))
@inline def unsafeFrom(str: String): NEString = {
require(str.nonEmpty)
new NEString(str)
}
@inline implicit def asIterable(ne: NEString): IterableOnce[Char] = ne.toIterable
}