Introduce associateWith and associateWithTo functions
#KT-13814
This commit is contained in:
@@ -1059,6 +1059,36 @@ public inline fun <T, K, V, M : MutableMap<in K, in V>> Iterable<T>.associateTo(
|
|||||||
return destination
|
return destination
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a [Map] where keys are elements from the given collection and values are
|
||||||
|
* produced by the [valueSelector] function applied to each element.
|
||||||
|
*
|
||||||
|
* If any two elements are equal, the last one gets added to the map.
|
||||||
|
*
|
||||||
|
* The returned map preserves the entry iteration order of the original collection.
|
||||||
|
*
|
||||||
|
* @sample samples.collections.Collections.Transformations.associateWith
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
public inline fun <K, V> Iterable<K>.associateWith(valueSelector: (K) -> V): Map<K, V> {
|
||||||
|
val result = LinkedHashMap<K, V>(mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16))
|
||||||
|
return associateWithTo(result, valueSelector)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates and returns the [destination] mutable map with key-value pairs for each element of the given collection,
|
||||||
|
* where key is the element itself and value is provided by the [valueSelector] function applied to that key.
|
||||||
|
*
|
||||||
|
* If any two elements are equal, the last one overwrites the former value in the map.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
public inline fun <K, V, M : MutableMap<in K, in V>> Iterable<K>.associateWithTo(destination: M, valueSelector: (K) -> V): M {
|
||||||
|
for (element in this) {
|
||||||
|
destination.put(element, valueSelector(element))
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends all elements to the given [destination] collection.
|
* Appends all elements to the given [destination] collection.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -642,6 +642,40 @@ public inline fun <T, K, V, M : MutableMap<in K, in V>> Sequence<T>.associateTo(
|
|||||||
return destination
|
return destination
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a [Map] where keys are elements from the given sequence and values are
|
||||||
|
* produced by the [valueSelector] function applied to each element.
|
||||||
|
*
|
||||||
|
* If any two elements are equal, the last one gets added to the map.
|
||||||
|
*
|
||||||
|
* The returned map preserves the entry iteration order of the original sequence.
|
||||||
|
*
|
||||||
|
* The operation is _terminal_.
|
||||||
|
*
|
||||||
|
* @sample samples.collections.Collections.Transformations.associateWith
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
public inline fun <K, V> Sequence<K>.associateWith(valueSelector: (K) -> V): Map<K, V> {
|
||||||
|
val result = LinkedHashMap<K, V>()
|
||||||
|
return associateWithTo(result, valueSelector)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates and returns the [destination] mutable map with key-value pairs for each element of the given sequence,
|
||||||
|
* where key is the element itself and value is provided by the [valueSelector] function applied to that key.
|
||||||
|
*
|
||||||
|
* If any two elements are equal, the last one overwrites the former value in the map.
|
||||||
|
*
|
||||||
|
* The operation is _terminal_.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
public inline fun <K, V, M : MutableMap<in K, in V>> Sequence<K>.associateWithTo(destination: M, valueSelector: (K) -> V): M {
|
||||||
|
for (element in this) {
|
||||||
|
destination.put(element, valueSelector(element))
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends all elements to the given [destination] collection.
|
* Appends all elements to the given [destination] collection.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -615,6 +615,36 @@ public inline fun <K, V, M : MutableMap<in K, in V>> CharSequence.associateTo(de
|
|||||||
return destination
|
return destination
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a [Map] where keys are characters from the given char sequence and values are
|
||||||
|
* produced by the [valueSelector] function applied to each character.
|
||||||
|
*
|
||||||
|
* If any two characters are equal, the last one gets added to the map.
|
||||||
|
*
|
||||||
|
* The returned map preserves the entry iteration order of the original char sequence.
|
||||||
|
*
|
||||||
|
* @sample samples.text.Strings.associateWith
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
public inline fun <V> CharSequence.associateWith(valueSelector: (Char) -> V): Map<Char, V> {
|
||||||
|
val result = LinkedHashMap<Char, V>(mapCapacity(length).coerceAtLeast(16))
|
||||||
|
return associateWithTo(result, valueSelector)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates and returns the [destination] mutable map with key-value pairs for each character of the given char sequence,
|
||||||
|
* where key is the character itself and value is provided by the [valueSelector] function applied to that key.
|
||||||
|
*
|
||||||
|
* If any two characters are equal, the last one overwrites the former value in the map.
|
||||||
|
*/
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
public inline fun <V, M : MutableMap<in Char, in V>> CharSequence.associateWithTo(destination: M, valueSelector: (Char) -> V): M {
|
||||||
|
for (element in this) {
|
||||||
|
destination.put(element, valueSelector(element))
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends all characters to the given [destination] collection.
|
* Appends all characters to the given [destination] collection.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -300,6 +300,14 @@ class Collections {
|
|||||||
|
|
||||||
class Transformations {
|
class Transformations {
|
||||||
|
|
||||||
|
@Sample
|
||||||
|
fun associateWith() {
|
||||||
|
val words = listOf("a", "abc", "ab", "def", "abcd")
|
||||||
|
val withLength = words.associateWith { it.length }
|
||||||
|
assertPrints(withLength.keys, "[a, abc, ab, def, abcd]")
|
||||||
|
assertPrints(withLength.values, "[1, 3, 2, 3, 4]")
|
||||||
|
}
|
||||||
|
|
||||||
@Sample
|
@Sample
|
||||||
fun groupBy() {
|
fun groupBy() {
|
||||||
val words = listOf("a", "abc", "ab", "def", "abcd")
|
val words = listOf("a", "abc", "ab", "def", "abcd")
|
||||||
|
|||||||
@@ -84,6 +84,15 @@ class Strings {
|
|||||||
assertPrints(result, "[az, by, cx]")
|
assertPrints(result, "[az, by, cx]")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Sample
|
||||||
|
fun associateWith() {
|
||||||
|
val string = "bonne journée"
|
||||||
|
// associate each character with its code
|
||||||
|
val result = string.associateWith { char -> char.toInt() }
|
||||||
|
// notice each letter occurs only once
|
||||||
|
assertPrints(result, "{b=98, o=111, n=110, e=101, =32, j=106, u=117, r=114, é=233}")
|
||||||
|
}
|
||||||
|
|
||||||
@Sample
|
@Sample
|
||||||
fun stringToByteArray() {
|
fun stringToByteArray() {
|
||||||
val charset = Charsets.UTF_8
|
val charset = Charsets.UTF_8
|
||||||
|
|||||||
@@ -358,6 +358,18 @@ class CollectionTest {
|
|||||||
assertEquals(namesByTeam, mutableNamesByTeam)
|
assertEquals(namesByTeam, mutableNamesByTeam)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun associateWith() {
|
||||||
|
val items = listOf("Alice", "Bob", "Carol")
|
||||||
|
val itemsWithTheirLength = items.associateWith { it.length }
|
||||||
|
|
||||||
|
assertEquals(mapOf("Alice" to 5, "Bob" to 3, "Carol" to 5), itemsWithTheirLength)
|
||||||
|
|
||||||
|
val updatedLength =
|
||||||
|
items.drop(1).associateWithTo(itemsWithTheirLength.toMutableMap()) { name -> name.toLowerCase().count { it in "aeuio" }}
|
||||||
|
|
||||||
|
assertEquals(mapOf("Alice" to 5, "Bob" to 1, "Carol" to 2), updatedLength)
|
||||||
|
}
|
||||||
|
|
||||||
@Test fun plusRanges() {
|
@Test fun plusRanges() {
|
||||||
val range1 = 1..3
|
val range1 = 1..3
|
||||||
val range2 = 4..7
|
val range2 = 4..7
|
||||||
|
|||||||
@@ -548,6 +548,18 @@ public class SequenceTest {
|
|||||||
assertEquals(listOf("act", "wast", "test"), sequenceOf("act", "test", "wast").sortedWith(comparator).toList())
|
assertEquals(listOf("act", "wast", "test"), sequenceOf("act", "test", "wast").sortedWith(comparator).toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun associateWith() {
|
||||||
|
val items = sequenceOf("Alice", "Bob", "Carol")
|
||||||
|
val itemsWithTheirLength = items.associateWith { it.length }
|
||||||
|
|
||||||
|
assertEquals(mapOf("Alice" to 5, "Bob" to 3, "Carol" to 5), itemsWithTheirLength)
|
||||||
|
|
||||||
|
val updatedLength =
|
||||||
|
items.drop(1).associateWithTo(itemsWithTheirLength.toMutableMap()) { name -> name.toLowerCase().count { it in "aeuio" }}
|
||||||
|
|
||||||
|
assertEquals(mapOf("Alice" to 5, "Bob" to 1, "Carol" to 2), updatedLength)
|
||||||
|
}
|
||||||
|
|
||||||
@Test fun orEmpty() {
|
@Test fun orEmpty() {
|
||||||
val s1: Sequence<Int>? = null
|
val s1: Sequence<Int>? = null
|
||||||
assertEquals(emptySequence(), s1.orEmpty())
|
assertEquals(emptySequence(), s1.orEmpty())
|
||||||
|
|||||||
@@ -1159,6 +1159,14 @@ class StringTest {
|
|||||||
assertEquals(listOf('A', 'A', 'B', 'D'), result[true])
|
assertEquals(listOf('A', 'A', 'B', 'D'), result[true])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test fun associateWith() = withOneCharSequenceArg("abc") { data ->
|
||||||
|
val result = data.associateWith { it + 1 }
|
||||||
|
assertEquals(mapOf('a' to 'b', 'b' to 'c', 'c' to 'd'), result)
|
||||||
|
|
||||||
|
val mutableResult = data.drop(1).associateWithTo(result.toMutableMap()) { it - 1 }
|
||||||
|
assertEquals(mapOf('a' to 'b', 'b' to 'a', 'c' to 'b'), mutableResult)
|
||||||
|
}
|
||||||
|
|
||||||
@Test fun joinToString() {
|
@Test fun joinToString() {
|
||||||
val data = "abcd".toList()
|
val data = "abcd".toList()
|
||||||
val result = data.joinToString("_", "(", ")")
|
val result = data.joinToString("_", "(", ")")
|
||||||
|
|||||||
+6
@@ -2084,6 +2084,8 @@ public final class kotlin/collections/CollectionsKt {
|
|||||||
public static final fun associateByTo (Ljava/lang/Iterable;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
public static final fun associateByTo (Ljava/lang/Iterable;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
public static final fun associateByTo (Ljava/lang/Iterable;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
public static final fun associateByTo (Ljava/lang/Iterable;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
public static final fun associateTo (Ljava/lang/Iterable;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
public static final fun associateTo (Ljava/lang/Iterable;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
|
public static final fun associateWith (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
|
public static final fun associateWithTo (Ljava/lang/Iterable;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
public static final fun averageOfByte (Ljava/lang/Iterable;)D
|
public static final fun averageOfByte (Ljava/lang/Iterable;)D
|
||||||
public static final fun averageOfDouble (Ljava/lang/Iterable;)D
|
public static final fun averageOfDouble (Ljava/lang/Iterable;)D
|
||||||
public static final fun averageOfFloat (Ljava/lang/Iterable;)D
|
public static final fun averageOfFloat (Ljava/lang/Iterable;)D
|
||||||
@@ -4356,6 +4358,8 @@ public final class kotlin/sequences/SequencesKt {
|
|||||||
public static final fun associateByTo (Lkotlin/sequences/Sequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
public static final fun associateByTo (Lkotlin/sequences/Sequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
public static final fun associateByTo (Lkotlin/sequences/Sequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
public static final fun associateByTo (Lkotlin/sequences/Sequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
public static final fun associateTo (Lkotlin/sequences/Sequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
public static final fun associateTo (Lkotlin/sequences/Sequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
|
public static final fun associateWith (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
|
public static final fun associateWithTo (Lkotlin/sequences/Sequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
public static final fun averageOfByte (Lkotlin/sequences/Sequence;)D
|
public static final fun averageOfByte (Lkotlin/sequences/Sequence;)D
|
||||||
public static final fun averageOfDouble (Lkotlin/sequences/Sequence;)D
|
public static final fun averageOfDouble (Lkotlin/sequences/Sequence;)D
|
||||||
public static final fun averageOfFloat (Lkotlin/sequences/Sequence;)D
|
public static final fun averageOfFloat (Lkotlin/sequences/Sequence;)D
|
||||||
@@ -4693,6 +4697,8 @@ public final class kotlin/text/StringsKt {
|
|||||||
public static final fun associateByTo (Ljava/lang/CharSequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
public static final fun associateByTo (Ljava/lang/CharSequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
public static final fun associateByTo (Ljava/lang/CharSequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
public static final fun associateByTo (Ljava/lang/CharSequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
public static final fun associateTo (Ljava/lang/CharSequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
public static final fun associateTo (Ljava/lang/CharSequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
|
public static final fun associateWith (Ljava/lang/CharSequence;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
|
public static final fun associateWithTo (Ljava/lang/CharSequence;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map;
|
||||||
public static final fun capitalize (Ljava/lang/String;)Ljava/lang/String;
|
public static final fun capitalize (Ljava/lang/String;)Ljava/lang/String;
|
||||||
public static final fun chunked (Ljava/lang/CharSequence;I)Ljava/util/List;
|
public static final fun chunked (Ljava/lang/CharSequence;I)Ljava/util/List;
|
||||||
public static final fun chunked (Ljava/lang/CharSequence;ILkotlin/jvm/functions/Function1;)Ljava/util/List;
|
public static final fun chunked (Ljava/lang/CharSequence;ILkotlin/jvm/functions/Function1;)Ljava/util/List;
|
||||||
|
|||||||
@@ -405,4 +405,66 @@ object Snapshots : TemplateGroupBase() {
|
|||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val f_associateWith = fn("associateWith(valueSelector: (K) -> V)") {
|
||||||
|
include(Iterables, Sequences, CharSequences)
|
||||||
|
} builder {
|
||||||
|
inline()
|
||||||
|
since("1.3")
|
||||||
|
typeParam("K", primary = true)
|
||||||
|
typeParam("V")
|
||||||
|
returns("Map<K, V>")
|
||||||
|
doc {
|
||||||
|
"""
|
||||||
|
Returns a [Map] where keys are ${f.element.pluralize()} from the given ${f.collection} and values are
|
||||||
|
produced by the [valueSelector] function applied to each ${f.element}.
|
||||||
|
|
||||||
|
If any two ${f.element.pluralize()} are equal, the last one gets added to the map.
|
||||||
|
|
||||||
|
The returned map preserves the entry iteration order of the original ${f.collection}.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
sample(when (family) {
|
||||||
|
CharSequences -> "samples.text.Strings.associateWith"
|
||||||
|
else -> "samples.collections.Collections.Transformations.associateWith"
|
||||||
|
})
|
||||||
|
body {
|
||||||
|
val resultMap = when (family) {
|
||||||
|
Iterables -> "LinkedHashMap<K, V>(mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16))"
|
||||||
|
CharSequences -> "LinkedHashMap<K, V>(mapCapacity(length).coerceAtLeast(16))"
|
||||||
|
else -> "LinkedHashMap<K, V>()"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
val result = $resultMap
|
||||||
|
return associateWithTo(result, valueSelector)
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val f_associateWithTo = fn("associateWithTo(destination: M, valueSelector: (K) -> V)") {
|
||||||
|
include(Iterables, Sequences, CharSequences)
|
||||||
|
} builder {
|
||||||
|
inline()
|
||||||
|
since("1.3")
|
||||||
|
typeParam("K", primary = true)
|
||||||
|
typeParam("V")
|
||||||
|
typeParam("M : MutableMap<in K, in V>")
|
||||||
|
returns("M")
|
||||||
|
doc {
|
||||||
|
"""
|
||||||
|
Populates and returns the [destination] mutable map with key-value pairs for each ${f.element} of the given ${f.collection},
|
||||||
|
where key is the ${f.element} itself and value is provided by the [valueSelector] function applied to that key.
|
||||||
|
|
||||||
|
If any two ${f.element.pluralize()} are equal, the last one overwrites the former value in the map.
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
"""
|
||||||
|
for (element in this) {
|
||||||
|
destination.put(element, valueSelector(element))
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user