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

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

The newest version!
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 NEStrings

* *

* 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 NEStrings

* *

* 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 NEStrings 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 NEStrings. * * @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 NEStrings. */ 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 NEStrings 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 NEStrings 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 NEStrings. * * @param size the number of characters per group * @return An iterator producing NEStrings 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 NEStrings 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 NEStrings, is non-empty. * * @return false */ def isEmpty: Boolean = false /** * Returns true to indicate this NEString, like all NEStrings, 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 NEStrings, 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 NEStrings 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 NEStrings 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 NEStrings 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 NEStrings, 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 NEStrings 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 NEStrings, 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 NEStrings. * * @param NEString: the NEString containing the elements to extract * @return an Seq containing this NEStrings 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 }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy