diff --git a/libraries/stdlib/samples/test/samples/collections/grouping.kt b/libraries/stdlib/samples/test/samples/collections/grouping.kt index 317b5fc14db..61636191bc4 100644 --- a/libraries/stdlib/samples/test/samples/collections/grouping.kt +++ b/libraries/stdlib/samples/test/samples/collections/grouping.kt @@ -6,8 +6,6 @@ package samples.collections import samples.* -import java.util.stream.Collector -import kotlin.test.* class Grouping { @@ -25,35 +23,34 @@ class Grouping { @Sample - fun aggregateEvenAndOdd() { - val intList = listOf(0, 1, 2, 3, 4, 5, 6) + fun aggregateByRadix() { + val numbers = listOf(3, 4, 5, 6, 7, 8, 9) - // to multiply even number by 10 - val aggregated = intList.groupingBy { it % 2 == 0 }.aggregate { key, acc: Int?, element, _ -> - when (key) { - true -> element * 10 + (acc ?: 0) - else -> element + (acc ?: 0) - } + val aggregated = numbers.groupingBy { it % 3 }.aggregate { key, accumulator: StringBuilder?, element, first -> + if (first) // first element + StringBuilder().append(key).append(":").append(element) + else + accumulator!!.append("-").append(element) } - assertPrints(aggregated, "{true=120, false=9}") + assertPrints(aggregated.values, "[0:3-6-9, 1:4-7, 2:5-8]") } @Sample - fun aggregateEvenAndOddTo() { - val intList = listOf(0, 1, 2, 3, 4, 5, 6) - val aggregated = mutableMapOf() + fun aggregateByRadixTo() { + val numbers = listOf(3, 4, 5, 6, 7, 8, 9) - // to multiply even number by 10 - intList.groupingBy { it % 2 == 0 }.aggregateTo(aggregated, { key, acc: Int?, element, _ -> - when (key) { - true -> element * 10 + (acc ?: 0) - else -> element + (acc ?: 0) - } - }) + val aggregated = numbers.groupingBy { it % 3 }.aggregateTo(mutableMapOf()) { key, accumulator: StringBuilder?, element, first -> + if (first) // first element + StringBuilder().append(key).append(":").append(element) + else + accumulator!!.append("-").append(element) + } - assertTrue(aggregated[true] == 120) - assertTrue(aggregated[false] == 9) + assertPrints(aggregated.values, "[0:3-6-9, 1:4-7, 2:5-8]") + + // aggregated is a mutable map + aggregated.clear() } @Sample @@ -63,8 +60,7 @@ class Grouping { val evenFruits = fruits.groupingBy { it.first() } .fold({ key, _ -> key to mutableListOf() }, { _, accumulator, element -> - if (element.length % 2 == 0) accumulator.second.add(element) - accumulator + accumulator.also { (_, list) -> if (element.length % 2 == 0) list.add(element) } }) val sorted = evenFruits.values.sortedBy { it.first } @@ -74,25 +70,18 @@ class Grouping { @Sample fun foldByEvenLengthWithComputedInitialValueTo() { val fruits = listOf("cherry", "blueberry", "citrus", "apple", "apricot", "banana", "coconut") - val evenFruits = mutableMapOf>>() - fruits.groupingBy { it.first() } - .foldTo(evenFruits, { key, _: String -> key to mutableListOf() }, + val evenFruits = fruits.groupingBy { it.first() } + .foldTo(mutableMapOf(), { key, _: String -> key to mutableListOf() }, { _, accumulator, element -> if (element.length % 2 == 0) accumulator.second.add(element) accumulator }) val sorted = evenFruits.values.sortedBy { it.first } + assertPrints(sorted, "[(a, []), (b, [banana]), (c, [cherry, citrus])]") - assertTrue(sorted.first().first == 'a') - assertTrue(sorted[0].second == emptyList()) - - assertTrue(sorted[1].first == 'b') - assertTrue(sorted[1].second == listOf("banana")) - - assertTrue(sorted.last().first == 'c') - assertTrue(sorted.last().second == listOf("cherry", "citrus")) + evenFruits.clear() // evenFruits is a mutable map } @Sample @@ -109,51 +98,43 @@ class Grouping { @Sample fun foldByEvenLengthWithConstantInitialValueTo() { val fruits = listOf("apple", "apricot", "banana", "blueberry", "cherry", "coconut") - val evenFruits = mutableMapOf>() // collect only even length Strings - fruits.groupingBy { it.first() } - .foldTo(evenFruits, listOf()) { acc, e -> if (e.length % 2 == 0) acc + e else acc } + val evenFruits = fruits.groupingBy { it.first() } + .foldTo(mutableMapOf(), emptyList()) { acc, e -> if (e.length % 2 == 0) acc + e else acc } - assertTrue(evenFruits['a'] == emptyList()) - assertTrue(evenFruits['b'] == listOf("banana")) - assertTrue(evenFruits['c'] == listOf("cherry")) + assertPrints(evenFruits, "{a=[], b=[banana], c=[cherry]}") + + evenFruits.clear() // evenFruits is a mutable map } @Sample - fun reduceByMaxOfContainsVowels() { + fun reduceByMaxVowels() { val animals = listOf("raccoon", "reindeer", "cow", "camel", "giraffe", "goat") // grouping by first char and collect only max of contains vowels - val maxVowels = animals.groupingBy { it.first() } - .reduce { _, a, b -> - if (a.count { it in "aeiou" } >= b.count { it in "aeiou" }) { - a - } else { - b - } - } + val compareByVowelCount = compareBy { s: String -> s.count { it in "aeiou" } } + + val maxVowels = animals.groupingBy { it.first() }.reduce { _, a, b -> maxOf(a, b, compareByVowelCount) } assertPrints(maxVowels, "{r=reindeer, c=camel, g=giraffe}") } @Sample - fun reduceByMaxOfContainsVowelsTo() { + fun reduceByMaxVowelsTo() { val animals = listOf("raccoon", "reindeer", "cow", "camel", "giraffe", "goat") val maxVowels = mutableMapOf() // grouping by first char and collect only max of contains vowels - animals.groupingBy { it.first() } - .reduceTo(maxVowels, { _, a, b -> - if (a.count { it in "aeiou" } >= b.count { it in "aeiou" }) { - a - } else { - b - } - }) + val compareByVowelCount = compareBy { s: String -> s.count { it in "aeiou" } } - assertTrue(maxVowels['r'] == "reindeer") - assertTrue(maxVowels['c'] == "camel") - assertTrue(maxVowels['g'] == "giraffe") + animals.groupingBy { it.first() }.reduceTo(maxVowels) { _, a, b -> maxOf(a, b, compareByVowelCount) } + + assertPrints(maxVowels, "{r=reindeer, c=camel, g=giraffe}") + + val moreAnimals = listOf("capybara", "rat") + moreAnimals.groupingBy { it.first() }.reduceTo(maxVowels) { _, a, b -> maxOf(a, b, compareByVowelCount) } + + assertPrints(maxVowels, "{r=reindeer, c=capybara, g=giraffe}") } } \ No newline at end of file diff --git a/libraries/stdlib/src/kotlin/collections/Grouping.kt b/libraries/stdlib/src/kotlin/collections/Grouping.kt index 028de766169..c920ab5032d 100644 --- a/libraries/stdlib/src/kotlin/collections/Grouping.kt +++ b/libraries/stdlib/src/kotlin/collections/Grouping.kt @@ -44,7 +44,7 @@ public interface Grouping { * - `first`: indicates whether it's the first `element` encountered in the group. * * @return a [Map] associating the key of each group with the result of aggregation of the group elements. - * @sample samples.collections.Grouping.aggregateEvenAndOdd + * @sample samples.collections.Grouping.aggregateByRadix */ @SinceKotlin("1.1") public inline fun Grouping.aggregate( @@ -70,7 +70,7 @@ public inline fun Grouping.aggregate( * then the elements being aggregated for that key are never considered as `first`. * * @return the [destination] map associating the key of each group with the result of aggregation of the group elements. - * @sample samples.collections.Grouping.aggregateEvenAndOddTo + * @sample samples.collections.Grouping.aggregateByRadixTo */ @SinceKotlin("1.1") public inline fun > Grouping.aggregateTo( @@ -202,7 +202,7 @@ public inline fun > Grouping.foldTo( * - `element`: the element from the source being accumulated. * * @return a [Map] associating the key of each group with the result of accumulating the group elements. - * @sample samples.collections.Grouping.reduceByMaxOfContainsVowels + * @sample samples.collections.Grouping.reduceByMaxVowels */ @SinceKotlin("1.1") public inline fun Grouping.reduce( @@ -229,7 +229,7 @@ public inline fun Grouping.reduce( * - `element`: the element from the source being folded; * * @return the [destination] map associating the key of each group with the result of accumulating the group elements. - * @sample samples.collections.Grouping.reduceByMaxOfContainsVowelsTo + * @sample samples.collections.Grouping.reduceByMaxVowelsTo */ @SinceKotlin("1.1") public inline fun > Grouping.reduceTo(