编程语言
179
groupBy(keySelector: (T) -> K): Map<K, List<T>>
将集合中的元素按照条件选择器keySelector
(是一个函数)分组,并返回Map。
代码示例:
>>> val words = listOf("a", "abc", "ab", "def", "abcd") >>> val lengthGroup = words.groupBy { it.length } >>> lengthGroup {1=[a], 3=[abc, def], 2=[ab], 4=[abcd]}
groupBy(keySelector: (T) -> K, valueTransform: (T) -> V)
分组函数还有一个是groupBy(keySelector: (T) -> K, valueTransform: (T) -> V)
,根据条件选择器keySelector和转换函数valueTransform分组。
代码示例
>>> val programmer = listOf("K&R" to "C", "Bjar" to "C++", "Linus" to "C", "James" to "Java") >>> programmer [(K&R, C), (Bjar, C++), (Linus, C), (James, Java)] >>> programmer.groupBy({it.second}, {it.first}) {C=[K&R, Linus], C++=[Bjar], Java=[James]}
这里涉及到一个 二元组Pair 类,该类是Kotlin提供的用来处理二元数据组的。 可以理解成Map中的一个键值对,比如Pair(“key”,”value”) 等价于 “key” to “value”。
我们再通过下面的代码示例,来看一下这两个分组的区别:
>>> val words = listOf("a", "abc", "ab", "def", "abcd") >>> words.groupBy( { it.length }) {1=[a], 3=[abc, def], 2=[ab], 4=[abcd]} >>> words.groupBy( { it.length },{it.contains("b")}) {1=[false], 3=[true, false], 2=[true], 4=[true]}
我们可以看出,后者是在前者的基础上又映射了一次{it.contains("b")}
,把第2次映射的结果放到返回的Map中了。
groupingBy(crossinline keySelector: (T) -> K): Grouping<T, K>
另外,我们还可以使用groupingBy(crossinline keySelector: (T) -> K): Grouping<T, K>
函数来创建一个Grouping
,然后调用计数函数eachCount
统计分组:
代码示例
>>> val words = "one two three four five six seven eight nine ten".split(' ') >>> words.groupingBy({it.first()}).eachCount() {o=1, t=3, f=2, s=2, e=1, n=1}
上面的例子是统计words列表的元素单词中首字母出现的频数。
其中,eachCount
函数定义如下:
@SinceKotlin("1.1") @JvmVersion public fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int> = // fold(0) { acc, e -> acc + 1 } optimized for boxing foldTo( destination = mutableMapOf(), initialValueSelector = { _, _ -> kotlin.jvm.internal.Ref.IntRef() }, operation = { _, acc, _ -> acc.apply { element += 1 } }) .mapValuesInPlace { it.value.element }