File: GroupingTest.kt

package info (click to toggle)
kotlin 1.3.31%2Bds1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 109,908 kB
  • sloc: java: 454,756; xml: 18,599; javascript: 10,452; sh: 513; python: 97; makefile: 69; ansic: 4
file content (117 lines) | stat: -rw-r--r-- 5,130 bytes parent folder | download | duplicates (2)
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)
    }
*/
}