集合的分组(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.pswp.cn/web/89443.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/89443.shtml
英文地址,请注明出处:http://en.pswp.cn/web/89443.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里云ssh证书过期,如果更换并上传到服务器

登录阿里云平台,在控制台中找到“数字证书管理服务”进入频道后,选择“SSL证书管理”点击“创建证书”,创建成功后,进入证书详情页选择“下载”板块,根据自身服务器类型,下载相应的证书即可服务器更新证书登…

【软件系统架构】系列七:系统性能——计算机性能深入解析

目录 一、什么是计算机性能? 二、计算机性能核心指标 1. CPU性能指标 2. 内存性能指标 3. 存储子系统性能 4. 网络性能指标 5. 系统资源使用与并发能力 三、性能瓶颈分析方法 四、计算机性能评测与对比 常见性能测试指标与工具: 五、计算机性…

基于现代R语言【Tidyverse、Tidymodel】的机器学习方法

机器学习已经成为继理论、实验和数值计算之后的科研“第四范式”,是发现新规律,总结和分析实验结果的利器。机器学习涉及的理论和方法繁多,编程相当复杂,一直是阻碍机器学习大范围应用的主要困难之一,由此诞生了Python…

Python暑期学习笔记5

时间:2025.7.18学习内容:【语法基础】while循环与循环嵌套一、循环语句循环流程图二、while循环基本格式:while条件:循环体(条件满足时段做的事情)改变变量死循环while True:循环体(要循环做的事…

world models and Human–Object Interaction (HOI)

Author: Chatgpt Here are several key research papers that explore the intersection of world models and Human–Object Interaction (HOI)—especially ones that build structured, object-centric representations from videos or use world-model-based learning to p…

无人值守共享自习室物联系统安全防线:从设备到数据的全面防护策略!

在“全民学习”浪潮的推动下,无人值守共享自习室凭借24小时开放、灵活预约和沉浸式体验,已成为城市学习空间的新形态。而当人力值守被物联网设备替代后,安全风险却从物理世界延伸到了数字世界。一套完整的自习室物联网系统包含门禁、传感器、…

【27】MFC入门到精通——MFC 修改用户界面登录IP IP Address Control

界面搭建 将【IP Address Control】控件,【Edit Control】控件和两个【button】控件分别拖入主界面 将ID分别修改为:IDC_IP_ADDRESS IDC_IPADDRESS_EDIT IDC_GET_BUTTON IDC_CLEAN_BUTTON添加变量 为【IP Address Control】控件添加变量【m_IPaddress】&…

MacOS安装linux虚拟机

在学习docker时用的云环境本身就是一个容器,启动docker总是各种问题,所以直接在本机上装一个虚拟机。 当前系统环境: 安装虚拟机软件 安装UTM 下载官网:https://mac.getutm.app/ uname -m查看一下指令架构,下载…

TimSort:论Java Arrays.sort的稳定性

TimSort 是一种混合的、稳定的排序算法,结合了归并排序(Merge Sort)和二分插入排序(Binary Insertion Sort)的优点,尤其适用于部分有序的数据。在 Java 中,Arrays.sort() 对对象数组排序时内部使…

企业数据生命周期安全架构设计

数据是企业的生命线,而安全则是这条生命线的保护神。今天我们就来聊聊如何为企业数据的一生一世构建一套坚不可摧的安全防护体系。 📚 文章目录 为什么需要数据生命周期安全架构数据生命周期全景图安全架构设计的核心原则各阶段安全防护策略整体安全架构…

【Java】字符串常量池

文章目录一.字符串常量池(StringTable)1.1 定义1.2 演示示例1.3 intern方法一.字符串常量池(StringTable) 1.1 定义 字符串常量词本质是一个固定大小的HashTable。当用一个字符串构造String对象时,首先会去StringTable中查看是否存在在字符串,如果存在…

数据通信与计算机网络——模拟传输

主要内容数字到模拟转换幅移键控ASK频移键控FSK相移键控PSK正交振幅调制QAM模拟信号调制调幅AM调频FM调相PM一、数字到模拟转换数字信号需要低通通道,如果现实应用中只有带通通道,只能选择模拟信号进行传输。将数字数据转换为带通模拟信号,传…

如何用Python并发下载?深入解析concurrent.futures 与期物机制

concurrent.futures模块的核心价值 Python的concurrent.futures模块提供了线程池(ThreadPoolExecutor)和进程池(ProcessPoolExecutor)两种并发模型,通过高层接口简化并发编程。其核心优势在于: 自动管理资源…

MMKV 存储json list数据(kotlin)

1、添加依赖与初始化 首先在 build.gradle 中添加 MMKV 依赖: implementationcom.tencent:mmkv:1.2.12 在 Application 类中初始化 MMKV: import android.app.Application import com.tencent.mmkv.MMKVclass MyApp : Application() { override fun onCreate() { super.o…

C++ -- STL-- stack and queue

////// 欢迎来到 aramae 的博客,愿 Bug 远离,好运常伴! ////// 博主的Gitee地址:阿拉美 (aramae) - Gitee.com 时代不会辜负长期主义者,愿每一个努力的人都能达到理想的彼岸。1. stack的介绍和使用 2. queue的介绍…

信息论至AI实践:交叉熵的原理全景与应用深度解析

1 定义与数学原理:从信息论到分布差异度量 交叉熵(Cross Entropy)是信息论中用于量化两个概率分布差异的核心概念,由Claude Shannon的信息论发展而来。它测量了在相同事件集合上,使用估计的概率分布q对服从真实概率分…

WAF 能防御哪些攻击?

WAF(Web 应用防火墙)是网站和Web应用的安全守门人,但很多用户对其具体防御范围一知半解。实际上,WAF 能针对性拦截多种网络攻击,从常见的注入攻击到复杂的恶意爬虫,覆盖Web安全的核心威胁。本文详解WAF的防…

闲庭信步使用图像验证平台加速FPGA的开发:第二十二课——图像直方图统计的FPGA实现

(本系列只需要modelsim即可完成数字图像的处理,每个工程都搭建了全自动化的仿真环境,只需要双击top_tb.bat文件就可以完成整个的仿真,大大降低了初学者的门槛!!!!如需要该系列的工程…

群晖中相册管理 immich大模型的使用

相对于其他的相册管理软件,Immich的智能搜索和人脸识别功能是其优势,通过应用机器学习模型,其智能搜索和人脸识别功能更为先进。 一、大模型的下载与安装 网上有大佬提供了相关大模型的下载:https://url22.ctfile.com/d/58003522…

在 Windows 上使用 Docker 运行 Elastic Open Crawler

作者:来自 Elastic Matt Nowzari 了解如何使用 Docker 在 Windows 环境中运行 Open Crawler。 了解将数据摄取到 Elasticsearch 的不同方式,并深入实践示例,尝试一些新方法。 Elasticsearch 拥有大量新功能,助你为特定场景构建最…