indexOfAny, lastIndexOfAny return an index value only (similar to indexOf, lastIndexOf).

findAnyOf, findLastAnyOf introduced to cover the case when an index and a matched string value is required.
This commit is contained in:
Ilya Gorbunov
2015-03-30 19:57:18 +03:00
parent bb8df6be4b
commit 536a977f5c
2 changed files with 113 additions and 55 deletions
+50 -22
View File
@@ -491,8 +491,7 @@ public fun String.endsWith(char: Char): Boolean = endsWith(char, ignoreCase = fa
// indexOfAny()
private fun String.indexOfAny(chars: CharArray, startIndex: Int, ignoreCase: Boolean, last: Boolean): Pair<Int, Char>? {
private fun String.findAnyOf(chars: CharArray, startIndex: Int, ignoreCase: Boolean, last: Boolean): Pair<Int, Char>? {
if (!ignoreCase && chars.size() == 1) {
val char = chars.single()
val index = if (!last) nativeIndexOf(char, startIndex) else nativeLastIndexOf(char, startIndex)
@@ -511,31 +510,31 @@ private fun String.indexOfAny(chars: CharArray, startIndex: Int, ignoreCase: Boo
}
/**
* Finds the first occurrence of any of the specified [chars] in this string, starting from the specified [startIndex] and
* Finds the index of the first occurrence of any of the specified [chars] in this string, starting from the specified [startIndex] and
* optionally ignoring the case.
*
* @param ignoreCase `true` to ignore character case when matching a character. By default `false`.
* @returns A pair of an index of the first occurrence of matched character from [chars] and the character matched or `null` if none of [chars] are found.
* @returns An index of the first occurrence of matched character from [chars] or -1 if none of [chars] are found.
*
*/
public fun String.indexOfAny(chars: CharArray, startIndex: Int = 0, ignoreCase: Boolean = false): Pair<Int, Char>? =
indexOfAny(chars, startIndex, ignoreCase, last = false)
public fun String.indexOfAny(chars: CharArray, startIndex: Int = 0, ignoreCase: Boolean = false): Int =
findAnyOf(chars, startIndex, ignoreCase, last = false)?.first ?: -1
/**
* Finds the last occurrence of any of the specified [chars] in this string, starting from the specified [startIndex] and
* Finds the index of the last occurrence of any of the specified [chars] in this string, starting from the specified [startIndex] and
* optionally ignoring the case.
*
* @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string.
* @param ignoreCase `true` to ignore character case when matching a character. By default `false`.
* @returns A pair of an index of the last occurrence of matched character from [chars] and the character matched or `null` if none of [chars] are found.
* @returns An index of the last occurrence of matched character from [chars] or -1 if none of [chars] are found.
*
*/
public fun String.lastIndexOfAny(chars: CharArray, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Pair<Int, Char>? =
indexOfAny(chars, startIndex, ignoreCase, last = true)
public fun String.lastIndexOfAny(chars: CharArray, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int =
findAnyOf(chars, startIndex, ignoreCase, last = true)?.first ?: -1
private fun String.indexOfAny(strings: Collection<String>, startIndex: Int, ignoreCase: Boolean, last: Boolean): Pair<Int, String>? {
private fun String.findAnyOf(strings: Collection<String>, startIndex: Int, ignoreCase: Boolean, last: Boolean): Pair<Int, String>? {
if (!ignoreCase && strings.size() == 1) {
val string = strings.single()
val index = if (!last) nativeIndexOf(string, startIndex) else nativeLastIndexOf(string, startIndex)
@@ -557,14 +556,14 @@ private fun String.indexOfAny(strings: Collection<String>, startIndex: Int, igno
* optionally ignoring the case.
*
* @param ignoreCase `true` to ignore character case when matching a string. By default `false`.
* @returns A pair of an index of the first occurrence of matched string from [stromgs] and the string matched or `null` if none of [strings] are found.
* @returns A pair of an index of the first occurrence of matched string from [strings] and the string matched or `null` if none of [strings] are found.
*
* To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from
* the beginning to the end of this string, and finds at each position the first element in [strings]
* that matches this string at that position.
*/
public fun String.indexOfAny(strings: Collection<String>, startIndex: Int = 0, ignoreCase: Boolean = false): Pair<Int, String>? =
indexOfAny(strings, startIndex, ignoreCase, last = false)
public fun String.findAnyOf(strings: Collection<String>, startIndex: Int = 0, ignoreCase: Boolean = false): Pair<Int, String>? =
findAnyOf(strings, startIndex, ignoreCase, last = false)
/**
* Finds the last occurrence of any of the specified [strings] in this string, starting from the specified [startIndex] and
@@ -578,8 +577,37 @@ public fun String.indexOfAny(strings: Collection<String>, startIndex: Int = 0, i
* the end toward the beginning of this string, and finds at each position the first element in [strings]
* that matches this string at that position.
*/
public fun String.lastIndexOfAny(strings: Collection<String>, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Pair<Int, String>? =
indexOfAny(strings, startIndex, ignoreCase, last = true)
public fun String.findLastAnyOf(strings: Collection<String>, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Pair<Int, String>? =
findAnyOf(strings, startIndex, ignoreCase, last = true)
/**
* Finds the index of the first occurrence of any of the specified [strings] in this string, starting from the specified [startIndex] and
* optionally ignoring the case.
*
* @param ignoreCase `true` to ignore character case when matching a string. By default `false`.
* @returns An index of the first occurrence of matched string from [strings] or -1 if none of [strings] are found.
*
* To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from
* the beginning to the end of this string, and finds at each position the first element in [strings]
* that matches this string at that position.
*/
public fun String.indexOfAny(strings: Collection<String>, startIndex: Int = 0, ignoreCase: Boolean = false): Int =
findAnyOf(strings, startIndex, ignoreCase, last = false)?.first ?: -1
/**
* Finds the index of the last occurrence of any of the specified [strings] in this string, starting from the specified [startIndex] and
* optionally ignoring the case.
*
* @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string.
* @param ignoreCase `true` to ignore character case when matching a string. By default `false`.
* @returns An index of the last occurrence of matched string from [strings] or -1 if none of [strings] are found.
*
* To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from
* the end toward the beginning of this string, and finds at each position the first element in [strings]
* that matches this string at that position.
*/
public fun String.lastIndexOfAny(strings: Collection<String>, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int =
findAnyOf(strings, startIndex, ignoreCase, last = true)?.first ?: -1
// indexOf
@@ -592,7 +620,7 @@ public fun String.lastIndexOfAny(strings: Collection<String>, startIndex: Int =
*/
public fun String.indexOf(char: Char, startIndex: Int = 0, ignoreCase: Boolean = false): Int {
return if (ignoreCase)
indexOfAny(charArray(char), startIndex, ignoreCase)?.first ?: -1
indexOfAny(charArray(char), startIndex, ignoreCase)
else
nativeIndexOf(char, startIndex)
}
@@ -605,7 +633,7 @@ public fun String.indexOf(char: Char, startIndex: Int = 0, ignoreCase: Boolean =
*/
public fun String.indexOf(string: String, startIndex: Int = 0, ignoreCase: Boolean = false): Int {
return if (ignoreCase)
indexOfAny(listOf(string), startIndex, ignoreCase)?.first ?: -1
indexOfAny(listOf(string), startIndex, ignoreCase)
else
nativeIndexOf(string, startIndex)
}
@@ -619,7 +647,7 @@ public fun String.indexOf(string: String, startIndex: Int = 0, ignoreCase: Boole
*/
public fun String.lastIndexOf(char: Char, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int {
return if (ignoreCase)
lastIndexOfAny(charArray(char), startIndex, ignoreCase)?.first ?: -1
lastIndexOfAny(charArray(char), startIndex, ignoreCase)
else
nativeLastIndexOf(char, startIndex)
}
@@ -633,7 +661,7 @@ public fun String.lastIndexOf(char: Char, startIndex: Int = lastIndex, ignoreCas
*/
public fun String.lastIndexOf(string: String, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int {
return if (ignoreCase)
lastIndexOfAny(listOf(string), startIndex, ignoreCase)?.first ?: -1
lastIndexOfAny(listOf(string), startIndex, ignoreCase)
else
nativeLastIndexOf(string, startIndex)
}
@@ -717,7 +745,7 @@ private class DelimitedRangesSequence(private val string: String, private val st
private fun String.rangesDelimitedBy(vararg delimiters: Char, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence<IntRange> {
require(limit >= 0, { "Limit must be non-negative, but was $limit" })
return DelimitedRangesSequence(this, startIndex, limit, { startIndex -> indexOfAny(delimiters, startIndex, ignoreCase = ignoreCase)?.let { Pair(it.first, 1) }})
return DelimitedRangesSequence(this, startIndex, limit, { startIndex -> findAnyOf(delimiters, startIndex, ignoreCase = ignoreCase, last = false)?.let { it.first to 1 } })
}
@@ -739,7 +767,7 @@ private fun String.rangesDelimitedBy(vararg delimiters: String, startIndex: Int
require(limit >= 0, { "Limit must be non-negative, but was $limit" } )
val delimitersList = delimiters.asList()
return DelimitedRangesSequence(this, startIndex, limit, { startIndex -> indexOfAny(delimitersList, startIndex, ignoreCase = ignoreCase)?.let { Pair(it.first, it.second.length() )} })
return DelimitedRangesSequence(this, startIndex, limit, { startIndex -> findAnyOf(delimitersList, startIndex, ignoreCase = ignoreCase, last = false)?.let { it.first to it.second.length ()} })
}
+63 -33
View File
@@ -315,57 +315,87 @@ class StringTest {
test fun indexOfAnyChar() {
val string = "abracadabra"
val chars = charArray('d','b')
assertEquals(1 to 'b', string.indexOfAny(chars))
assertEquals(6 to 'd', string.indexOfAny(chars, startIndex = 2))
assertEquals(null, string.indexOfAny(chars, startIndex = 9))
assertEquals(1, string.indexOfAny(chars))
assertEquals(6, string.indexOfAny(chars, startIndex = 2))
assertEquals(-1, string.indexOfAny(chars, startIndex = 9))
assertEquals(8 to 'b', string.lastIndexOfAny(chars))
assertEquals(6 to 'd', string.lastIndexOfAny(chars, startIndex = 7))
assertEquals(null, string.lastIndexOfAny(chars, startIndex = 0))
assertEquals(8, string.lastIndexOfAny(chars))
assertEquals(6, string.lastIndexOfAny(chars, startIndex = 7))
assertEquals(-1, string.lastIndexOfAny(chars, startIndex = 0))
assertEquals(null, string.indexOfAny(charArray()))
assertEquals(-1, string.indexOfAny(charArray()))
}
test fun indexOfAnyCharIgnoreCase() {
val string = "abraCadabra"
val chars = charArray('B','c')
assertEquals(1 to 'B', string.indexOfAny(chars, ignoreCase = true))
assertEquals(4 to 'c', string.indexOfAny(chars, startIndex = 2, ignoreCase = true))
assertEquals(null, string.indexOfAny(chars, startIndex = 9, ignoreCase = true))
assertEquals(1, string.indexOfAny(chars, ignoreCase = true))
assertEquals(4, string.indexOfAny(chars, startIndex = 2, ignoreCase = true))
assertEquals(-1, string.indexOfAny(chars, startIndex = 9, ignoreCase = true))
assertEquals(8 to 'B', string.lastIndexOfAny(chars, ignoreCase = true))
assertEquals(4 to 'c', string.lastIndexOfAny(chars, startIndex = 7, ignoreCase = true))
assertEquals(null, string.lastIndexOfAny(chars, startIndex = 0, ignoreCase = true))
assertEquals(8, string.lastIndexOfAny(chars, ignoreCase = true))
assertEquals(4, string.lastIndexOfAny(chars, startIndex = 7, ignoreCase = true))
assertEquals(-1, string.lastIndexOfAny(chars, startIndex = 0, ignoreCase = true))
}
test fun indexOfAnyString() {
val string = "abracadabra"
val substrings = listOf("rac", "ra")
assertEquals(2 to "rac", string.indexOfAny(substrings))
assertEquals(9 to "ra", string.indexOfAny(substrings, startIndex = 3))
assertEquals(2 to "ra", string.indexOfAny(substrings.reverse()))
assertEquals(null, string.indexOfAny(substrings, 10))
assertEquals(2, string.indexOfAny(substrings))
assertEquals(9, string.indexOfAny(substrings, startIndex = 3))
assertEquals(2, string.indexOfAny(substrings.reverse()))
assertEquals(-1, string.indexOfAny(substrings, 10))
assertEquals(9 to "ra", string.lastIndexOfAny(substrings))
assertEquals(2 to "rac", string.lastIndexOfAny(substrings, startIndex = 8))
assertEquals(2 to "ra", string.lastIndexOfAny(substrings.reverse(), startIndex = 8))
assertEquals(null, string.lastIndexOfAny(substrings, 1))
assertEquals(9, string.lastIndexOfAny(substrings))
assertEquals(2, string.lastIndexOfAny(substrings, startIndex = 8))
assertEquals(2, string.lastIndexOfAny(substrings.reverse(), startIndex = 8))
assertEquals(-1, string.lastIndexOfAny(substrings, 1))
assertEquals(0 to "", string.indexOfAny(listOf("dab", "")), "empty strings are not ignored")
assertEquals(null, string.indexOfAny(listOf()))
assertEquals(0, string.indexOfAny(listOf("dab", "")), "empty strings are not ignored")
assertEquals(-1, string.indexOfAny(listOf()))
}
test fun indexOfAnyStringIgnoreCase() {
val string = "aBraCadaBrA"
val substrings = listOf("rAc", "Ra")
assertEquals(2 to substrings[0], string.indexOfAny(substrings, ignoreCase = true))
assertEquals(9 to substrings[1], string.indexOfAny(substrings, startIndex = 3, ignoreCase = true))
assertEquals(null, string.indexOfAny(substrings, startIndex = 10, ignoreCase = true))
assertEquals(2, string.indexOfAny(substrings, ignoreCase = true))
assertEquals(9, string.indexOfAny(substrings, startIndex = 3, ignoreCase = true))
assertEquals(-1, string.indexOfAny(substrings, startIndex = 10, ignoreCase = true))
assertEquals(9 to substrings[1], string.lastIndexOfAny(substrings, ignoreCase = true))
assertEquals(2 to substrings[0], string.lastIndexOfAny(substrings, startIndex = 8, ignoreCase = true))
assertEquals(null, string.lastIndexOfAny(substrings, startIndex = 1, ignoreCase = true))
assertEquals(9, string.lastIndexOfAny(substrings, ignoreCase = true))
assertEquals(2, string.lastIndexOfAny(substrings, startIndex = 8, ignoreCase = true))
assertEquals(-1, string.lastIndexOfAny(substrings, startIndex = 1, ignoreCase = true))
}
test fun findAnyOfStrings() {
val string = "abracadabra"
val substrings = listOf("rac", "ra")
assertEquals(2 to "rac", string.findAnyOf(substrings))
assertEquals(9 to "ra", string.findAnyOf(substrings, startIndex = 3))
assertEquals(2 to "ra", string.findAnyOf(substrings.reverse()))
assertEquals(null, string.findAnyOf(substrings, 10))
assertEquals(9 to "ra", string.findLastAnyOf(substrings))
assertEquals(2 to "rac", string.findLastAnyOf(substrings, startIndex = 8))
assertEquals(2 to "ra", string.findLastAnyOf(substrings.reverse(), startIndex = 8))
assertEquals(null, string.findLastAnyOf(substrings, 1))
assertEquals(0 to "", string.findAnyOf(listOf("dab", "")), "empty strings are not ignored")
assertEquals(null, string.findAnyOf(listOf()))
}
test fun findAnyOfStringsIgnoreCase() {
val string = "aBraCadaBrA"
val substrings = listOf("rAc", "Ra")
assertEquals(2 to substrings[0], string.findAnyOf(substrings, ignoreCase = true))
assertEquals(9 to substrings[1], string.findAnyOf(substrings, startIndex = 3, ignoreCase = true))
assertEquals(null, string.findAnyOf(substrings, startIndex = 10, ignoreCase = true))
assertEquals(9 to substrings[1], string.findLastAnyOf(substrings, ignoreCase = true))
assertEquals(2 to substrings[0], string.findLastAnyOf(substrings, startIndex = 8, ignoreCase = true))
assertEquals(null, string.findLastAnyOf(substrings, startIndex = 1, ignoreCase = true))
}
test fun indexOfChar() {
@@ -378,8 +408,8 @@ class StringTest {
assertEquals(2, string.lastIndexOf('e', 3))
for (startIndex in -1..string.length()+1) {
assertEquals(string.indexOfAny(charArray('e'), startIndex)?.first ?: -1, string.indexOf('e', startIndex))
assertEquals(string.lastIndexOfAny(charArray('e'), startIndex)?.first ?: -1, string.lastIndexOf('e', startIndex))
assertEquals(string.indexOfAny(charArray('e'), startIndex), string.indexOf('e', startIndex))
assertEquals(string.lastIndexOfAny(charArray('e'), startIndex), string.lastIndexOf('e', startIndex))
}
}
@@ -395,8 +425,8 @@ class StringTest {
for (startIndex in -1..string.length()+1){
assertEquals(string.indexOfAny(charArray('e'), startIndex, ignoreCase = true)?.first ?: -1, string.indexOf('E', startIndex, ignoreCase = true))
assertEquals(string.lastIndexOfAny(charArray('E'), startIndex, ignoreCase = true)?.first ?: -1, string.lastIndexOf('e', startIndex, ignoreCase = true))
assertEquals(string.indexOfAny(charArray('e'), startIndex, ignoreCase = true), string.indexOf('E', startIndex, ignoreCase = true))
assertEquals(string.lastIndexOfAny(charArray('E'), startIndex, ignoreCase = true), string.lastIndexOf('e', startIndex, ignoreCase = true))
}
}