Introduce new overloads of flatMap and flatMapTo

- Sequence<T>.flatMap((T) -> Iterable<R>)
- Iterable<T>.flatMap((T) -> Sequence<R>)
- Array<T>.flatMap((T) -> Sequence<R>)
- Map.flatMap((Entry) -> Sequence<R>)

KT-34506
This commit is contained in:
Ilya Gorbunov
2020-04-24 05:15:07 +03:00
parent 562788ceb9
commit bdd53ee9cd
10 changed files with 233 additions and 9 deletions
@@ -10032,6 +10032,19 @@ public inline fun <R> CharArray.flatMap(transform: (Char) -> Iterable<R>): List<
return flatMapTo(ArrayList<R>(), transform)
}
/**
* Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array.
*
* @sample samples.collections.Collections.Transformations.flatMap
*/
@SinceKotlin("1.4")
@OptIn(kotlin.experimental.ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
@kotlin.jvm.JvmName("flatMapSequence")
public inline fun <T, R> Array<out T>.flatMap(transform: (T) -> Sequence<R>): List<R> {
return flatMapTo(ArrayList<R>(), transform)
}
/**
* Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination].
*/
@@ -10131,6 +10144,21 @@ public inline fun <R, C : MutableCollection<in R>> CharArray.flatMapTo(destinati
return destination
}
/**
* Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination].
*/
@SinceKotlin("1.4")
@OptIn(kotlin.experimental.ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
@kotlin.jvm.JvmName("flatMapSequenceTo")
public inline fun <T, R, C : MutableCollection<in R>> Array<out T>.flatMapTo(destination: C, transform: (T) -> Sequence<R>): C {
for (element in this) {
val list = transform(element)
destination.addAll(list)
}
return destination
}
/**
* Groups elements of the original array by the key returned by the given [keySelector] function
* applied to each element and returns a map where each group key is associated with a list of corresponding elements.
@@ -1286,6 +1286,19 @@ public inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): Lis
return flatMapTo(ArrayList<R>(), transform)
}
/**
* Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original collection.
*
* @sample samples.collections.Collections.Transformations.flatMap
*/
@SinceKotlin("1.4")
@OptIn(kotlin.experimental.ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
@kotlin.jvm.JvmName("flatMapSequence")
public inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Sequence<R>): List<R> {
return flatMapTo(ArrayList<R>(), transform)
}
/**
* Appends all elements yielded from results of [transform] function being invoked on each element of original collection, to the given [destination].
*/
@@ -1297,6 +1310,21 @@ public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapTo(dest
return destination
}
/**
* Appends all elements yielded from results of [transform] function being invoked on each element of original collection, to the given [destination].
*/
@SinceKotlin("1.4")
@OptIn(kotlin.experimental.ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
@kotlin.jvm.JvmName("flatMapSequenceTo")
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapTo(destination: C, transform: (T) -> Sequence<R>): C {
for (element in this) {
val list = transform(element)
destination.addAll(list)
}
return destination
}
/**
* Groups elements of the original collection by the key returned by the given [keySelector] function
* applied to each element and returns a map where each group key is associated with a list of corresponding elements.
@@ -46,6 +46,19 @@ public inline fun <K, V, R> Map<out K, V>.flatMap(transform: (Map.Entry<K, V>) -
return flatMapTo(ArrayList<R>(), transform)
}
/**
* Returns a single list of all elements yielded from results of [transform] function being invoked on each entry of original map.
*
* @sample samples.collections.Collections.Transformations.flatMap
*/
@SinceKotlin("1.4")
@OptIn(kotlin.experimental.ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
@kotlin.jvm.JvmName("flatMapSequence")
public inline fun <K, V, R> Map<out K, V>.flatMap(transform: (Map.Entry<K, V>) -> Sequence<R>): List<R> {
return flatMapTo(ArrayList<R>(), transform)
}
/**
* Appends all elements yielded from results of [transform] function being invoked on each entry of original map, to the given [destination].
*/
@@ -57,6 +70,21 @@ public inline fun <K, V, R, C : MutableCollection<in R>> Map<out K, V>.flatMapTo
return destination
}
/**
* Appends all elements yielded from results of [transform] function being invoked on each entry of original map, to the given [destination].
*/
@SinceKotlin("1.4")
@OptIn(kotlin.experimental.ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
@kotlin.jvm.JvmName("flatMapSequenceTo")
public inline fun <K, V, R, C : MutableCollection<in R>> Map<out K, V>.flatMapTo(destination: C, transform: (Map.Entry<K, V>) -> Sequence<R>): C {
for (element in this) {
val list = transform(element)
destination.addAll(list)
}
return destination
}
/**
* Returns a list containing the results of applying the given [transform] function
* to each entry in the original map.
@@ -765,6 +765,21 @@ public fun <T> Sequence<T>.toSet(): Set<T> {
return toCollection(LinkedHashSet<T>()).optimizeReadOnlySet()
}
/**
* Returns a single sequence of all elements from results of [transform] function being invoked on each element of original sequence.
*
* The operation is _intermediate_ and _stateless_.
*
* @sample samples.collections.Collections.Transformations.flatMap
*/
@SinceKotlin("1.4")
@OptIn(kotlin.experimental.ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
@kotlin.jvm.JvmName("flatMapIterable")
public fun <T, R> Sequence<T>.flatMap(transform: (T) -> Iterable<R>): Sequence<R> {
return FlatteningSequence(this, transform, { it.iterator() })
}
/**
* Returns a single sequence of all elements from results of [transform] function being invoked on each element of original sequence.
*
@@ -776,6 +791,23 @@ public fun <T, R> Sequence<T>.flatMap(transform: (T) -> Sequence<R>): Sequence<R
return FlatteningSequence(this, transform, { it.iterator() })
}
/**
* Appends all elements yielded from results of [transform] function being invoked on each element of original sequence, to the given [destination].
*
* The operation is _terminal_.
*/
@SinceKotlin("1.4")
@OptIn(kotlin.experimental.ExperimentalTypeInference::class)
@OverloadResolutionByLambdaReturnType
@kotlin.jvm.JvmName("flatMapIterableTo")
public inline fun <T, R, C : MutableCollection<in R>> Sequence<T>.flatMapTo(destination: C, transform: (T) -> Iterable<R>): C {
for (element in this) {
val list = transform(element)
destination.addAll(list)
}
return destination
}
/**
* Appends all elements yielded from results of [transform] function being invoked on each element of original sequence, to the given [destination].
*
@@ -12,6 +12,7 @@ import test.assertTypeEquals
import test.collections.behaviors.*
import test.comparisons.STRING_CASE_INSENSITIVE_ORDER
import test.text.isAsciiLetter
import kotlin.math.exp
import kotlin.test.*
import kotlin.random.Random
@@ -1756,6 +1757,15 @@ class ArraysTest {
assertEquals(listOf(2), arrayOf("a", null, "test").mapIndexedNotNull { index, it -> it?.run { if (index != 0) length / index else null } })
}
@Test fun flatMap() {
val data = arrayOf(arrayOf(1, 2, 3), arrayOf(4, 5, 6))
val result1 = data.flatMap { it.asList() }
val result2 = data.flatMap { it.asSequence() }
val expected = (data[0] + data[1]).toList()
assertEquals(expected, result1)
assertEquals(expected, result2)
}
@Test fun flattenArray() {
val arr1: Array<Array<Int>> = arrayOf(arrayOf(1, 2, 3), arrayOf(4, 5, 6))
val arr2: Array<out Array<Int>> = arr1
@@ -46,6 +46,17 @@ class CollectionTest {
assertStaticAndRuntimeTypeIs<List<String>>(foo)
}
@Test fun flatMap() {
val source = listOf(null, "foo", "bar")
val result1 = source.flatMap { it.orEmpty().asSequence() }
val result2 = source.flatMap { it.orEmpty().asIterable() }
val expected = "foobar".toList()
assertEquals(expected, result1)
assertEquals(expected, result2)
}
/*
@Test fun mapNotNull() {
val data = listOf(null, "foo", null, "bar")
+16 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -216,6 +216,21 @@ class MapTest {
assertEquals(mapOf(8 to "Mells"), m3)
}
@Test fun flatMap() {
fun <T> list(entry: Map.Entry<T, T>): List<T> = listOf(entry.key, entry.value)
fun <T> seq(entry: Map.Entry<T, T>): Sequence<T> = sequenceOf(entry.key, entry.value)
val m = mapOf("x" to 1, "y" to 0)
val result1 = m.flatMap { list(it) }
val result2 = m.flatMap { seq(it) }
val result3 = m.flatMap(::list)
val result4 = m.flatMap(::seq)
val expected = listOf("x", 1, "y", 0)
assertEquals(expected, result1)
assertEquals(expected, result2)
assertEquals(expected, result3)
assertEquals(expected, result4)
}
@Test fun createFrom() {
val pairs = arrayOf("a" to 1, "b" to 2)
val expected = mapOf(*pairs)
@@ -572,18 +572,24 @@ public class SequenceTest {
}
@Test fun flatMap() {
val result = sequenceOf(1, 2).flatMap { (0..it).asSequence() }
assertEquals(listOf(0, 1, 0, 1, 2), result.toList())
val result1 = sequenceOf(1, 2).flatMap { (0..it).asSequence() }
val result2 = sequenceOf(1, 2).flatMap { 0..it }
val expected = listOf(0, 1, 0, 1, 2)
assertEquals(expected, result1.toList())
assertEquals(expected, result2.toList())
}
@Test fun flatMapOnEmpty() {
val result = sequenceOf<Int>().flatMap { (0..it).asSequence() }
assertTrue(result.none())
assertTrue(sequenceOf<Int>().flatMap { sequenceOf(1) }.none())
assertTrue(sequenceOf<Int>().flatMap { listOf(1) }.none())
}
@Test fun flatMapWithEmptyItems() {
val result = sequenceOf(1, 2, 4).flatMap { if (it == 2) sequenceOf<Int>() else (it - 1..it).asSequence() }
assertEquals(listOf(0, 1, 3, 4), result.toList())
val result1 = sequenceOf(1, 2, 4).flatMap { if (it == 2) sequenceOf<Int>() else (it - 1..it).asSequence() }
val result2 = sequenceOf(1, 2, 4).flatMap { if (it == 2) emptyList<Int>() else it - 1..it }
val expected = listOf(0, 1, 3, 4)
assertEquals(expected, result1.toList())
assertEquals(expected, result2.toList())
}
@Test fun flatten() {
@@ -1087,6 +1087,8 @@ public final class kotlin/collections/ArraysKt {
public static final fun flatMap ([Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun flatMap ([SLkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun flatMap ([ZLkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun flatMapSequence ([Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun flatMapSequenceTo ([Ljava/lang/Object;Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
public static final fun flatMapTo ([BLjava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
public static final fun flatMapTo ([CLjava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
public static final fun flatMapTo ([DLjava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
@@ -2136,6 +2138,8 @@ public final class kotlin/collections/CollectionsKt {
public static final fun firstOrNull (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun firstOrNull (Ljava/util/List;)Ljava/lang/Object;
public static final fun flatMap (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun flatMapSequence (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun flatMapSequenceTo (Ljava/lang/Iterable;Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
public static final fun flatMapTo (Ljava/lang/Iterable;Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
public static final fun flatten (Ljava/lang/Iterable;)Ljava/util/List;
public static final fun fold (Ljava/lang/Iterable;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
@@ -2401,6 +2405,8 @@ public final class kotlin/collections/MapsKt {
public static final fun filterTo (Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
public static final fun filterValues (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
public static final fun flatMap (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun flatMapSequence (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun flatMapSequenceTo (Ljava/util/Map;Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
public static final fun flatMapTo (Ljava/util/Map;Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
public static final fun forEach (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)V
public static final fun getOrImplicitDefaultNullable (Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;
@@ -4780,6 +4786,8 @@ public final class kotlin/sequences/SequencesKt {
public static final fun firstOrNull (Lkotlin/sequences/Sequence;)Ljava/lang/Object;
public static final fun firstOrNull (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun flatMap (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
public static final fun flatMapIterable (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence;
public static final fun flatMapIterableTo (Lkotlin/sequences/Sequence;Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
public static final fun flatMapTo (Lkotlin/sequences/Sequence;Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
public static final fun flatten (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
public static final fun flattenSequenceOfIterable (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
@@ -304,7 +304,37 @@ object Mapping : TemplateGroupBase() {
}
specialFor(Sequences) {
inline(Inline.No)
signature("flatMap(transform: (T) -> Sequence<R>)")
since("1.4")
annotation("@OptIn(kotlin.experimental.ExperimentalTypeInference::class)")
annotation("@OverloadResolutionByLambdaReturnType")
annotation("""@kotlin.jvm.JvmName("flatMapIterable")""")
doc { "Returns a single sequence of all elements from results of [transform] function being invoked on each element of original sequence." }
returns("Sequence<R>")
body {
"return FlatteningSequence(this, transform, { it.iterator() })"
}
}
}
val f_flatMapSequence = fn("flatMap(transform: (T) -> Sequence<R>)") {
include(Sequences, Iterables, ArraysOfObjects, Maps)
} builder {
inline()
doc { "Returns a single list of all elements yielded from results of [transform] function being invoked on each ${f.element} of original ${f.collection}." }
sample("samples.collections.Collections.Transformations.flatMap")
typeParam("R")
returns("List<R>")
body {
"return flatMapTo(ArrayList<R>(), transform)"
}
if (f != Sequences) {
since("1.4")
annotation("@OptIn(kotlin.experimental.ExperimentalTypeInference::class)")
annotation("@OverloadResolutionByLambdaReturnType")
annotation("""@kotlin.jvm.JvmName("flatMapSequence")""")
}
specialFor(Sequences) {
inline(Inline.No)
doc { "Returns a single sequence of all elements from results of [transform] function being invoked on each element of original sequence." }
returns("Sequence<R>")
body {
@@ -322,7 +352,35 @@ object Mapping : TemplateGroupBase() {
doc { "Appends all elements yielded from results of [transform] function being invoked on each ${f.element} of original ${f.collection}, to the given [destination]." }
specialFor(Sequences) {
signature("flatMapTo(destination: C, transform: (T) -> Sequence<R>)")
since("1.4")
annotation("@OptIn(kotlin.experimental.ExperimentalTypeInference::class)")
annotation("@OverloadResolutionByLambdaReturnType")
annotation("""@kotlin.jvm.JvmName("flatMapIterableTo")""")
}
typeParam("R")
typeParam("C : MutableCollection<in R>")
returns("C")
body {
"""
for (element in this) {
val list = transform(element)
destination.addAll(list)
}
return destination
"""
}
}
val f_flatMapToSequence = fn("flatMapTo(destination: C, transform: (T) -> Sequence<R>)") {
include(Sequences, Iterables, ArraysOfObjects, Maps)
} builder {
inline()
doc { "Appends all elements yielded from results of [transform] function being invoked on each ${f.element} of original ${f.collection}, to the given [destination]." }
if (f != Sequences) {
since("1.4")
annotation("@OptIn(kotlin.experimental.ExperimentalTypeInference::class)")
annotation("@OverloadResolutionByLambdaReturnType")
annotation("""@kotlin.jvm.JvmName("flatMapSequenceTo")""")
}
typeParam("R")
typeParam("C : MutableCollection<in R>")