Introduce filterIndexed

#KT-9502 Fixed
This commit is contained in:
Ilya Gorbunov
2015-11-07 17:55:33 +03:00
parent ee759c10c8
commit 008a8059cf
9 changed files with 310 additions and 27 deletions
+171 -18
View File
@@ -2986,68 +2986,221 @@ public inline fun ShortArray.dropWhile(predicate: (Short) -> Boolean): List<Shor
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun <T> Array<out T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate)
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun BooleanArray.filter(predicate: (Boolean) -> Boolean): List<Boolean> {
return filterTo(ArrayList<Boolean>(), predicate)
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun ByteArray.filter(predicate: (Byte) -> Boolean): List<Byte> {
return filterTo(ArrayList<Byte>(), predicate)
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun CharArray.filter(predicate: (Char) -> Boolean): List<Char> {
return filterTo(ArrayList<Char>(), predicate)
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun DoubleArray.filter(predicate: (Double) -> Boolean): List<Double> {
return filterTo(ArrayList<Double>(), predicate)
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun FloatArray.filter(predicate: (Float) -> Boolean): List<Float> {
return filterTo(ArrayList<Float>(), predicate)
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun IntArray.filter(predicate: (Int) -> Boolean): List<Int> {
return filterTo(ArrayList<Int>(), predicate)
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun LongArray.filter(predicate: (Long) -> Boolean): List<Long> {
return filterTo(ArrayList<Long>(), predicate)
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun ShortArray.filter(predicate: (Short) -> Boolean): List<Short> {
return filterTo(ArrayList<Short>(), predicate)
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun <T> Array<out T>.filterIndexed(predicate: (Int, T) -> Boolean): List<T> {
return filterIndexedTo(ArrayList<T>(), predicate)
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun BooleanArray.filterIndexed(predicate: (Int, Boolean) -> Boolean): List<Boolean> {
return filterIndexedTo(ArrayList<Boolean>(), predicate)
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun ByteArray.filterIndexed(predicate: (Int, Byte) -> Boolean): List<Byte> {
return filterIndexedTo(ArrayList<Byte>(), predicate)
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun CharArray.filterIndexed(predicate: (Int, Char) -> Boolean): List<Char> {
return filterIndexedTo(ArrayList<Char>(), predicate)
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun DoubleArray.filterIndexed(predicate: (Int, Double) -> Boolean): List<Double> {
return filterIndexedTo(ArrayList<Double>(), predicate)
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun FloatArray.filterIndexed(predicate: (Int, Float) -> Boolean): List<Float> {
return filterIndexedTo(ArrayList<Float>(), predicate)
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun IntArray.filterIndexed(predicate: (Int, Int) -> Boolean): List<Int> {
return filterIndexedTo(ArrayList<Int>(), predicate)
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun LongArray.filterIndexed(predicate: (Int, Long) -> Boolean): List<Long> {
return filterIndexedTo(ArrayList<Long>(), predicate)
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun ShortArray.filterIndexed(predicate: (Int, Short) -> Boolean): List<Short> {
return filterIndexedTo(ArrayList<Short>(), predicate)
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <T, C : MutableCollection<in T>> Array<out T>.filterIndexedTo(destination: C, predicate: (Int, T) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Boolean>> BooleanArray.filterIndexedTo(destination: C, predicate: (Int, Boolean) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Byte>> ByteArray.filterIndexedTo(destination: C, predicate: (Int, Byte) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Char>> CharArray.filterIndexedTo(destination: C, predicate: (Int, Char) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Double>> DoubleArray.filterIndexedTo(destination: C, predicate: (Int, Double) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Float>> FloatArray.filterIndexedTo(destination: C, predicate: (Int, Float) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Int>> IntArray.filterIndexedTo(destination: C, predicate: (Int, Int) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Long>> LongArray.filterIndexedTo(destination: C, predicate: (Int, Long) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Short>> ShortArray.filterIndexedTo(destination: C, predicate: (Int, Short) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Returns a list containing all elements not matching the given [predicate].
*/
@@ -3199,7 +3352,7 @@ public inline fun <C : MutableCollection<in Short>> ShortArray.filterNotTo(desti
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <T, C : MutableCollection<in T>> Array<out T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
@@ -3207,7 +3360,7 @@ public inline fun <T, C : MutableCollection<in T>> Array<out T>.filterTo(destina
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Boolean>> BooleanArray.filterTo(destination: C, predicate: (Boolean) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
@@ -3215,7 +3368,7 @@ public inline fun <C : MutableCollection<in Boolean>> BooleanArray.filterTo(dest
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Byte>> ByteArray.filterTo(destination: C, predicate: (Byte) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
@@ -3223,7 +3376,7 @@ public inline fun <C : MutableCollection<in Byte>> ByteArray.filterTo(destinatio
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Char>> CharArray.filterTo(destination: C, predicate: (Char) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
@@ -3231,7 +3384,7 @@ public inline fun <C : MutableCollection<in Char>> CharArray.filterTo(destinatio
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Double>> DoubleArray.filterTo(destination: C, predicate: (Double) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
@@ -3239,7 +3392,7 @@ public inline fun <C : MutableCollection<in Double>> DoubleArray.filterTo(destin
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Float>> FloatArray.filterTo(destination: C, predicate: (Float) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
@@ -3247,7 +3400,7 @@ public inline fun <C : MutableCollection<in Float>> FloatArray.filterTo(destinat
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Int>> IntArray.filterTo(destination: C, predicate: (Int) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
@@ -3255,7 +3408,7 @@ public inline fun <C : MutableCollection<in Int>> IntArray.filterTo(destination:
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Long>> LongArray.filterTo(destination: C, predicate: (Long) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
@@ -3263,7 +3416,7 @@ public inline fun <C : MutableCollection<in Long>> LongArray.filterTo(destinatio
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <C : MutableCollection<in Short>> ShortArray.filterTo(destination: C, predicate: (Short) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
+19 -2
View File
@@ -668,12 +668,29 @@ public inline fun <T> Iterable<T>.dropWhile(predicate: (T) -> Boolean): List<T>
}
/**
* Returns a list containing all elements matching the given [predicate].
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate)
}
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun <T> Iterable<T>.filterIndexed(predicate: (Int, T) -> Boolean): List<T> {
return filterIndexedTo(ArrayList<T>(), predicate)
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterIndexedTo(destination: C, predicate: (Int, T) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Returns a list containing all elements not matching the given [predicate].
*/
@@ -705,7 +722,7 @@ public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterNotTo(desti
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
+20 -2
View File
@@ -356,12 +356,30 @@ public fun <T> Sequence<T>.dropWhile(predicate: (T) -> Boolean): Sequence<T> {
}
/**
* Returns a sequence containing all elements matching the given [predicate].
* Returns a sequence containing only elements matching the given [predicate].
*/
public fun <T> Sequence<T>.filter(predicate: (T) -> Boolean): Sequence<T> {
return FilteringSequence(this, true, predicate)
}
/**
* Returns a sequence containing only elements matching the given [predicate].
*/
public fun <T> Sequence<T>.filterIndexed(predicate: (Int, T) -> Boolean): Sequence<T> {
// TODO: Rewrite with generalized MapFilterIndexingSequence
return TransformingSequence(FilteringSequence(IndexingSequence(this), true, { predicate(it.index, it.value) }), { it.value })
}
/**
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <T, C : MutableCollection<in T>> Sequence<T>.filterIndexedTo(destination: C, predicate: (Int, T) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.add(element)
}
return destination
}
/**
* Returns a sequence containing all elements not matching the given [predicate].
*/
@@ -393,7 +411,7 @@ public inline fun <T, C : MutableCollection<in T>> Sequence<T>.filterNotTo(desti
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all elements matching the given [predicate] to the given [destination].
*/
public inline fun <T, C : MutableCollection<in T>> Sequence<T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
+25 -1
View File
@@ -517,6 +517,30 @@ public inline fun String.filter(predicate: (Char) -> Boolean): String {
return filterTo(StringBuilder(), predicate).toString()
}
/**
* Returns a char sequence containing only those characters from the original char sequence that match the given [predicate].
*/
public inline fun CharSequence.filterIndexed(predicate: (Int, Char) -> Boolean): CharSequence {
return filterIndexedTo(StringBuilder(), predicate)
}
/**
* Returns a string containing only those characters from the original string that match the given [predicate].
*/
public inline fun String.filterIndexed(predicate: (Int, Char) -> Boolean): String {
return filterIndexedTo(StringBuilder(), predicate).toString()
}
/**
* Appends all characters matching the given [predicate] to the given [destination].
*/
public inline fun <C : Appendable> CharSequence.filterIndexedTo(destination: C, predicate: (Int, Char) -> Boolean): C {
forEachIndexed { index, element ->
if (predicate(index, element)) destination.append(element)
}
return destination
}
/**
* Returns a char sequence containing only those characters from the original char sequence that do not match the given [predicate].
*/
@@ -560,7 +584,7 @@ public inline fun <C : Appendable> CharSequence.filterTo(destination: C, predica
}
/**
* Appends all elements matching the given [predicate] into the given [destination].
* Appends all characters matching the given [predicate] to the given [destination].
*/
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
public inline fun <C : Appendable> String.filterTo(destination: C, predicate: (Char) -> Boolean): C {
@@ -736,6 +736,15 @@ class ArraysTest {
expect(listOf("b"), { arrayOf("a", "b").filter { it > "a" } })
}
@test fun filterIndexed() {
expect(listOf(), { intArrayOf().filterIndexed { i, v -> i > v } })
expect(listOf(2, 5, 8), { intArrayOf(2, 4, 3, 5, 8).filterIndexed { index, value -> index % 2 == value % 2 } })
expect(listOf<Long>(2, 5, 8), { longArrayOf(2, 4, 3, 5, 8).filterIndexed { index, value -> index % 2 == (value % 2).toInt() } })
expect(listOf<Byte>(2, 5, 8), { byteArrayOf(2, 4, 3, 5, 8).filterIndexed { index, value -> index % 2 == (value % 2).toInt() } })
expect(listOf('9', 'e', 'a'), { charArrayOf('9', 'e', 'd', 'a').filterIndexed { index, c -> c == 'a' || index < 2 }})
expect(listOf("a", "c", "d"), { arrayOf("a", "b", "c", "d").filterIndexed { index, s -> s == "a" || index >= 2 } })
}
@test fun filterNot() {
expect(listOf(), { intArrayOf().filterNot { it > 2 } })
expect(listOf(1), { intArrayOf(1).filterNot { it > 2 } })
@@ -146,6 +146,11 @@ abstract class IterableTests<T : Iterable<String>>(val data: T, val empty: T) {
assertEquals(listOf("foo"), foo)
}
@Test fun filterIndexed() {
val result = data.filterIndexed { index, value -> value.first() == ('a' + index) }
assertEquals(listOf("bar"), result)
}
@Test
fun drop() {
val foo = data.drop(1)
@@ -45,6 +45,10 @@ public class SequenceTest {
}
}
@test fun filterIndexed() {
assertEquals(listOf(1, 2, 5, 13, 34), fibonacci().filterIndexed { index, value -> index % 2 == 1 }.take(5).toList())
}
@test fun filterNullable() {
val data = sequenceOf(null, "foo", null, "bar")
val filtered = data.filter { it == null || it == "foo" }
+9
View File
@@ -746,6 +746,15 @@ class StringTest {
assertContentEquals("abcd", arg1("a1b2c3d4").filterNot { it.isAsciiDigit() })
}
@test fun filterIndexed() {
val data = "abedcf"
assertEquals("abdf", data.filterIndexed { index, c -> c == 'a' + index })
}
@test fun filterIndexedCharSequence() = withOneCharSequenceArg("abedcf") { data ->
assertContentEquals("abdf", data.filterIndexed { index, c -> c == 'a' + index })
}
@test fun all() = withOneCharSequenceArg("AbCd") { data ->
assertTrue {
data.all { it.isAsciiLetter() }