1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package test.collections
import kotlin.test.*
class GroupingTest {
@Test fun groupingProducers() {
fun <T, K> verifyGrouping(grouping: Grouping<T, K>, expectedElements: List<T>, expectedKeys: List<K>) {
val elements = grouping.sourceIterator().asSequence().toList()
val keys = elements.map { grouping.keyOf(it) } // TODO: replace with grouping::keyOf when supported in JS
assertEquals(expectedElements, elements)
assertEquals(expectedKeys, keys)
}
val elements = listOf("foo", "bar", "value", "x")
val keySelector: (String) -> Int = { it.length }
val keys = elements.map(keySelector)
fun verifyGrouping(grouping: Grouping<String, Int>) = verifyGrouping(grouping, elements, keys)
verifyGrouping(elements.groupingBy { it.length })
verifyGrouping(elements.toTypedArray().groupingBy(keySelector))
verifyGrouping(elements.asSequence().groupingBy(keySelector))
val charSeq = "some sequence of chars"
verifyGrouping(charSeq.groupingBy { it.toInt() }, charSeq.toList(), charSeq.map { it.toInt() })
}
// aggregate and aggregateTo operations are not tested, but they're used in every other operation
@Test fun foldWithConstantInitialValue() {
val elements = listOf("foo", "bar", "flea", "zoo", "biscuit")
// only collect strings with even length
val result = elements.groupingBy { it.first() }.fold(listOf<String>()) { acc, e -> if (e.length % 2 == 0) acc + e else acc }
assertEquals(mapOf('f' to listOf("flea"), 'b' to emptyList(), 'z' to emptyList()), result)
val moreElements = listOf("fire", "zero", "abstract")
val result2 = moreElements.groupingBy { it.first() }.foldTo(HashMap(result), listOf()) { acc, e -> if (e.length % 2 == 0) acc + e else acc }
assertEquals(mapOf('f' to listOf("flea", "fire"), 'b' to emptyList(), 'z' to listOf("zero"), 'a' to listOf("abstract")), result2)
}
data class Collector<out K, V>(val key: K, val values: MutableList<V> = mutableListOf<V>())
@Test fun foldWithComputedInitialValue() {
fun <K> Collector<K, String>.accumulateIfEven(e: String) = apply { if (e.length % 2 == 0) values.add(e) }
fun <K, V> Collector<K, V>.toPair() = key to values as List<V>
val elements = listOf("foo", "bar", "flea", "zoo", "biscuit")
val result = elements.groupingBy { it.first() }
.fold({ k, _ -> Collector<Char, String>(k) }, { _, acc, e -> acc.accumulateIfEven(e) })
val ordered = result.values.sortedBy { it.key }.map { it.toPair() }
assertEquals(listOf('b' to emptyList(), 'f' to listOf("flea"), 'z' to emptyList()), ordered)
val moreElements = listOf("fire", "zero")
val result2 = moreElements.groupingBy { it.first() }
.foldTo(HashMap(result),
{ k, _ -> error("should not be called for $k") },
{ _, acc, e -> acc.accumulateIfEven(e) })
val ordered2 = result2.values.sortedBy { it.key }.map { it.toPair() }
assertEquals(listOf('b' to emptyList(), 'f' to listOf("flea", "fire"), 'z' to listOf("zero")), ordered2)
}
inline fun <T, K : Comparable<K>> maxOfBy(a: T, b: T, keySelector: (T) -> K) = if (keySelector(a) >= keySelector(b)) a else b
@Test fun reduce() {
val elements = listOf("foo", "bar", "flea", "zoo", "biscuit")
fun Char.isVowel() = this in "aeiou"
fun String.countVowels() = count(Char::isVowel)
val maxVowels = elements.groupingBy { it.first() }.reduce { _, a, b -> maxOfBy(a, b, String::countVowels) }
assertEquals(mapOf('f' to "foo", 'b' to "biscuit", 'z' to "zoo"), maxVowels)
val elements2 = listOf("bar", "z", "fork")
val concats = elements2.groupingBy { it.first() }.reduceTo(HashMap(maxVowels)) { _, acc, e -> acc + e }
assertEquals(mapOf('f' to "foofork", 'b' to "biscuitbar", 'z' to "zooz"), concats)
}
@Test fun countEach() {
val elements = listOf("foo", "bar", "flea", "zoo", "biscuit")
val counts = elements.groupingBy { it.first() }.eachCount()
assertEquals(mapOf('f' to 2, 'b' to 2, 'z' to 1), counts)
val elements2 = arrayOf("zebra", "baz", "cab")
val counts2 = elements2.groupingBy { it.last() }.eachCountTo(HashMap(counts))
assertEquals(mapOf('f' to 2, 'b' to 3, 'a' to 1, 'z' to 2), counts2)
}
/*
@Test fun sumEach() {
val values = listOf("k" to 50, "b" to 20, "k" to 1000 )
val summary = values.groupingBy { it.first }.eachSumOf { it.second }
assertEquals(mapOf("k" to 1050, "b" to 20), summary)
val values2 = listOf("key", "ball", "builder", "alpha")
val summary2 = values2.groupingBy { it.first().toString() }.eachSumOfTo(HashMap(summary)) { it.length }
assertEquals(mapOf("k" to 1053, "b" to 31, "a" to 5), summary2)
}
*/
}
|