当前位置: 首页 > news >正文

Kotlin集合分组

集合的分组(Grouping)

在之前的学习中,我们已经学会了如何对集合进行过滤、排序或执行聚合操作。

在本节中,我们将学习如何对集合元素进行分组,以便以最适合我们任务的方式呈现信息。


分组(Grouping)

在 Kotlin 中,有一些扩展函数可以用来对集合元素进行分组,其中一个就是 groupBy()。它接收一个 lambda 表达式,并返回一个 Map,其中的键(key)是分组依据,值(value)则是对应的集合元素组成的列表。

fun main() {val names = listOf("John", "Jane", "Mary", "Peter", "John", "Jane", "Mary", "Peter")// 按名字的首字母进行分组val groupedNames = names.groupBy { it.first() }println(groupedNames) // {J=[John, Jane, John, Jane], M=[Mary, Mary], P=[Peter, Peter]}
}

代码解释:
在上面的示例中,我们按名字的首字母进行分组:可以看到返回的 Map 中,键是名字的首字母,值是所有以该字母开头的名字列表。例如,键 J 对应的值是 [John, Jane, John, Jane]


你还可以在 groupBy() 中传入第二个 lambda 作为转换函数(valueTransform)。这样就能在分组时同时对元素进行变换。如下所示,我们将分组的元素转换为大写:

fun main() {val names = listOf("John", "Jane", "Mary", "Peter", "John", "Jane", "Mary", "Peter")// 按名字长度分组,并将每个名字转为大写fun main() {val names = listOf("John", "Jane", "Mary", "Peter", "John", "Jane", "Mary", "Peter")// 按名字长度分组,并将每个名字转为大写​val groupedNames2 = names.groupBy(keySelector = { it.length },valueTransform = { it.uppercase() })println(groupedNames2) // {4=[JOHN, JANE, MARY, JOHN, JANE, MARY], 5=[PETER, PETER]}
}val groupedNames2 = names.groupBy(keySelector = { it.length },              // 分组键:名字长度valueTransform = { it.uppercase() }       // 值变换:转为大写)println(groupedNames2) // 输出:{4=[JOHN, JANE, MARY, JOHN, JANE, MARY], 5=[PETER, PETER]}
}

分组与附加操作

有时我们想对所有分组同时进行某种操作。我们可以使用 groupingBy() 方法,它返回一个 Grouping 实例,允许以“懒方式”对各组进行操作(即在执行操作前不会真正构建分组)。

常见方法:
  • eachCount():计算每组中元素的数量,返回一个 Map,键是分组键,值是该组的元素数量。

  • fold():带有初始值,从左到右依次将操作应用于累加器与每个元素。如果集合为空,返回初始值。
    可以提供一个 initialValueSelector 函数用于设置初始值。

    • .fold(initialValue) { acc, element -> ... }
  • reduce():从第一元素开始进行累加操作(没有初始值),如果集合为空会抛出异常。可使用 reduceOrNull() 以防止异常。

    • .groupingBy { ... }.reduce { key, acc, element -> ... }
fun main() {val names = listOf("John", "Jane", "Mary", "Peter", "John", "Jane", "Mary", "Peter")// 按首字母分组,并统计每组数量val groupedNames3 = names.groupingBy { it.first() }.eachCount()println(groupedNames3) // {J=4, M=2, P=2}// 按首字母分组,累加每组中名字的总长度val groupedNames4 = names.groupingBy { it.first() }.fold(0) { acc, name -> acc + name.length }println(groupedNames4) // {J=16, M=8, P=10}// 按名字长度分组,保留每组中最长的名字val groupedNames5 = names.groupingBy { it.length }.reduce { _, acc, name -> if (name.length > acc.length) name else acc }println(groupedNames5) // {4=John, 5=Peter}
}

使用 aggregate() 聚合

使用 aggregate() 函数,可以对每个分组应用操作并返回结果。它提供了一种通用方式来执行分组操作(在 foldreduce 不满足需求时)。
语法:

aggregate { key, accumulator: R?, element, first ->// 返回新的 accumulator(累积值)
}
  • key:当前分组的键,比如 J, M, P

  • accumulator:上一次累积的值,第一次为 null

  • element:当前正在处理的元素(比如 "John")。

  • first:是否是该组的第一个元素。

示例:

fun main() {val names = listOf("John", "Jane", "Mary", "Peter", "John", "Jane", "Mary", "Peter")// 使用 aggregate 获取每组的元素数量val groupedNames6 = names.groupingBy { it.first() }.aggregate { _, accumulator: Int?, _, first ->if (first) 1 else accumulator!! + 1}println(groupedNames6) // {J=4, M=2, P=2}// 判断每组中所有名字的长度是否都是偶数val groupedNames7 = names.groupingBy { it.first() }.aggregate { _, accumulator: Boolean?, element, first ->if (first) element.length % 2 == 0 else accumulator!! && element.length % 2 == 0}println(groupedNames7) // {J=true, M=true, P=false}
}

总结

在本节中,我们学习了如何使用 groupBygroupingBy 函数对集合中的元素进行分组。这是处理集合数据时非常重要的技能。

http://www.lryc.cn/news/592071.html

相关文章:

  • 黑马Node.js全套入门教程,nodejs新教程含es6模块化+npm+express+webpack+promise等_ts对象笔记
  • Kotlin集合过滤
  • 【Python】LEGB作用域 + re模块 + 正则表达式
  • uni-app 跳转页面传参
  • SpringCloud相关总结
  • 牛油果果实检测-目标检测数据集(真实环境下)
  • 基于SpringBoot 投票系统 【源码+LW+PPT+部署】
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 基于jieba实现词频统计
  • 在 React 中根据数值动态设置 SVG 线条粗细
  • Hadoop与云原生集成:弹性扩缩容与OSS存储分离架构深度解析
  • VSCode - VSCode 快速跳转标签页
  • 135. Java 泛型 - 无界通配符
  • Android CountDownTimer
  • Ubuntu系统下交叉编译Android的X265库
  • UVC for USBCamera in Android - 篇二
  • 股指期货的杠杆比例一般是多少?
  • 【软件系统架构】系列七:系统性能——路由器性能深入解析
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - jieba库分词简介及使用
  • 短视频矩阵系统哪家好?全面解析与推荐
  • 短视频矩阵系统:从源头到开发的全面解析
  • 【unity实战】使用unity的Navigation+LineRenderer实现一个3D人物寻路提前指示预测移动轨迹的效果,并可以适配不同的地形
  • Charles 中文版介绍与使用指南 强大抓包工具助力 API 调试与网络优化
  • 网络编程(modbus,3握4挥)
  • 新书推介 | 吉林大学出版教材《汽车智能辅助驾驶系统技术》,国产仿真工具链GCKontrol-GCAir教学应用
  • mybatisdemo(黑马)
  • S7-1200 Profinet 的诊断功能
  • 嵌入式教育的云端革命:零边界实验室如何重塑未来工程师
  • 硬核电子工程:从硅片到系统的全栈实战指南—— 融合电路理论、嵌入式开发与PCB设计的工程艺术
  • 第三章自定义检视面板_创建自定义编辑器类_检测与应用修改(本章进度(2/9))
  • Xilinx Zynq:一款适用于软件定义无线电的现代片上系统