Scala011--Scala中的常用集合函数及操作Ⅱ

news2025/4/14 19:42:49

在上一篇文章中我已经接触并认识了几个常用的集合函数:foreach,sorted,sortBy,sortWith,flatten,map,flatMap。

接下来在这一篇文章中我将继续学习剩下的几个集合函数。

目录

一,filter函数 

​编辑 练习题1:如何过滤出大于2的奇数? 

练习题2:如何通过fliter和三元运算符过滤出大于2的奇数?

二,reduce函数及reduceLeft函数

1,reduce:无嵌套的列表 :只是一个列表集合序列

2,reduce:嵌套有对偶元组的列表:列表里面嵌套对偶元组

3,reduceLeft:无嵌套的列表

三,reduceRight函数

四,fold函数及foldLeft函数

五,foldRight函数

六,aggregate函数及par函数

1,非并行集合使用aggregate函数

2,并行集合使用aggregate函数


 

一,filter函数 

filter翻译为过滤,过滤器,所以filter函数就是用来过滤集合序列中的元素的。例如,现在我想要获取该数据结构中的偶数:

 那么我就可以如下编写:

scala> val im_list=List(1,2,8,10)  // 列表集合序列
im_list: List[Int] = List(1, 2, 8, 10)

scala> im_list.filter(f=>f%2==0)   // 过滤出偶数
res0: List[Int] = List(2, 8, 10)

如上,我向filter函数中传入了一个参数f,并且该参数f代表列表中的每一个元素1,2,8,10

但是如果我的元素是在嵌套的集合序列中又该怎么过滤出偶数?如下数据:

scala> val list_arr=List(Array(1,2,8),Array(10))  // 列表集合序列中嵌套了数组集合序列

 我记起之前学过的嵌套集合如果想要得到里面的元素的话得先要进行扁平化操作,于是我先使用了flatten函数对该数据结构进行扁平化操作:

 扁平化之后的数据是及其可爱的,现在我就可以对其进行过滤操作(过滤出偶数):

 练习题1:如何过滤出大于2的奇数? 

要处理的集合序列(列表中嵌套列表):List(List(1,2,8),List(10,12,15))

scala> val list_list=List(List(1,2,8),List(10,12,15))  // 列表嵌套列表

 现在我去过滤出大于2的奇数:

scala> list_list.flatten.filter(f=>f%2!=0&&f>2)

如上,我就过滤出了在集合序列中大于2的奇数:15

练习题2:如何通过fliter和三元运算符过滤出大于2的奇数?

在Scala中其实是没有三元运算符这种概念的,但是Scala也能够通过

 if  (条件)   true else  false实现三元运算符的功能,现在我将其和filter结合起来一起用:

 如上也可以得到结果。

二,reduce函数及reduceLeft函数

reduce函数需要我传入对偶元组,并且对偶元组中的两个参数分别代表集合序列中的第一个及后面的元素。这么一说可能有点抽象,但是使用代码敲出来效果之后就会形象许多。

1,reduce:无嵌套的列表 :只是一个列表集合序列

待处理的集合序列:List(1,2,8,10)

scala> val im_list=List(1,2,8,10)

接下来使用reduce函数来对该集合序列进行求和:

scala> im_list.reduce((a,b)=>a+b)  // 使用reduce函数并让元素之间相加得到元素和

 这个时候我又想到了之前还有一个列表和数组都有的求和函数sum,使用它也能得到一样的结果:

scala> im_list.sum   // 调用求和函数

 现在我想要知道reduce中的a和b都分别是什么数字,那么就可以在函数里面加一条打印语句(在加上打印语句时,需要使用花括号将打印语句和运算表达式包裹起来,并且需要注意的是最好每一句都换行,别写在同一行,不然就会报错):

 如下编写代码才会正确:

scala> im_list.reduce(   // 调用reduce函数
     | (a,b) => {        // 传入一个对偶元组
     | println(s"a=${a},b=${b}")   // 打印对应的a和b
     | a+b})             //  a和b要进行的运算

如上,我可以看到,当我们使用了reduce函数来求集合序列中的元素和时,a只会是两个值:一个是集合序列中的第一个元素,其他都是a与b通过表达式得到的值,因为集合序列中的第一个元素被a拿走了,所以b的值只会从集合序列中的第二个元素开始取。

在上式中,使用了a+b的表达式,所以a的值就会是a(a=1,3,11)与b(b=2,8,10)相加的结果。

在使用了reduce函数之后必须要有返回值,如上,我的返回的值为a+b即a最后的值为a+b的值。

 并且,对于reduce函数来说,它的返回值类型和传入的参数类型必须保持一致,不然就会报错:

如上,因为返回值是字符串,但是传入的参数都是int类型(整数类型)的,所以就会提示提示我类型不匹配。

2,reduce:嵌套有对偶元组的列表:列表里面嵌套对偶元组

之前我已经能够用非嵌套的集合序列来调用reduce函数,实现一系列的操作,但是如果我们的列表里面嵌套了对偶元组:List(("张三",19),("李四",22),("王五",35))

那么如果想要将对偶元组中的数字都取出来并进行求和运算的话,我该怎么办?这个时候需要注意的是因为原来的集合序列是含有对偶元组的,所以我们在使用reduce函数时,返回值也应该是对偶元组,处理如下:

scala> list_tup2.reduce(   // 对含有对偶元组的列表集合序列进行处理
     | (a,b)=>("age sum is",a._2+b._2)   //  因为含有字符串,所以返回值也得有字符串,与求和后的结果组合成对偶元组
     | )

3,reduceLeft:无嵌套的列表

reduceLeft函数和reduce函数一样,a的取值都是将集合序列最左边的数值作为起始值,并随着使用表达式的结果而变化,b的值依旧是只能从集合序列中从左往右取。例如,现在有一个列表集合序列List(1,2,3,4),当我们使用reduce函数并将其表达式设置为a+b,那么a的值就会是:1(a的初始值即集合序列中的第一个元素),1+2(a+b,b为集合序列中的第二个元素),1+2+3(a的值为上一步计算的结果,b的值依旧是从集合序列中以此选取),1+2+3+4。

b的值为:2,3,4。

接下来我使用代码来看一下具体的效果:

scala> list.reduceLeft(
     | (a,b) =>{
     | println(s"a:${a},b:${b}")  // 打印a和b具体的值
     | a+b   // 表达式
     | }
     | )

 如果我使用reduce函数的话,结果都是一样的:

 所以,reduce函数和reduceLeft函数的使用看个人喜欢就行。

接下来去认识一个与reduce和reduceLeft函数相反的函数reduceRight函数。

三,reduceRight函数

reduceRight函数与reduce及reduceLeft函数不同,其中b的初始化值是从集合序列的最后一个元素选取即集合序列的最右边的元素为a的第一个值。之后,a的取值就是从集合序列中的倒数第二个开始选取。例如List(1,2,3,4),如果我们对其使用reduceRight函数,那么b的值就会是:4,4+3,4+3+2,4+3+2+1。a的值会是3,2,1。最后b的值是10。如下:

scala> list.reduceRight(
     | (a,b)=>
     | {
     | println(s"a:${a},b:${b}")
     | a+b}
     | )

如上,我可以发现现在变成了a的值从集合序列中选取,而b的值是经过表达式之后的结果(b的初始值为集合序列中的最后一个元素)。

四,fold函数及foldLeft函数

fold函数及foldLeft函数和之前的reduce及reduceLeft函数相比,可以给第一个数指定一个积累的初始值。例如集合序列:List(1,2,3,4)使用reduce或redueLeft函数时,a的初始化值一定是集合序列中的第一个元素,但是如果使用了fold或者是foldLeft函数的话,a的初始化值可以不从集合序列中选取,而是可以指定。那么究竟是怎么样的?现在我使用代码来查看相关的结果:

scala> list.fold(10)(  // 指定a的初始化值为10
     | (a,b)=>{
     | println(s"a:${a},b:${b}")
     | a+b
     | }
     | )

 如上,我可以看到,a的值不再是从集合序列中选取,而是fold函数中的第一个参数10,当a不从集合序列中选取初始化值时,b的值就可以从集合序列中的第一个元素开始选取。

当然,使用foldLeft函数和fold函数实现的效果一样。

scala> list.foldLeft(10)(
     | (a,b)=>{
     | println(s"a:${a},b:${b}")
     | a+b
     | }
     | )

五,foldRight函数

foldRight函数和reduceRight函数的区别在与foldRight函数可以指定b的初始化值,而不是从集合序列中选取。并且b的初始化值就是foldRight函数中的指定的第一个参数值。

现在我使用具体的代码来看看具体的效果:

scala> list.foldRight(10)(
     | (a,b)=>{
     | println(s"a:${a},b:${b}")
     | a+b
     | }
     | )

 如上,我们可以看到,foldRight中的a和b的运算逻辑其实还是和reduceRight函数一样的,只是b的取值可以指定了而已。

六,aggregate函数及par函数

aggregate函数相比于reduce,reduceLeft函数,aggregate函数可以像fold函数那样传入积累的初始化值,并且也有fold函数没有的功能:可以让传入的参数执行两个表达式,而不仅仅是一个(但是想要两个表达式都执行需要条件)。

相比于fold,foldLeft函数,aggregate函数可以定义两个表达式,第一个表达式为seqOp,第二个表达式为comOp。只有当待处理的集合序列是并行集合,才会去执行comOp表达式。现在我去使用代码来看一下它们的具体效果。

par函数最主要的作用就是将集合序列转换成并行集合。

1,非并行集合使用aggregate函数

现在我们对集合序列List(1,2,3,4)来使用aggregate函数,并定义两个表达式都用于对集合中的元素求和:

scala> list.aggregate(10)(
     | (a,b)=>{
     |  println(s"a:${a},b:${b}")
     | a+b // 全局聚合
     | },
     | (a,b)=>{
     |  println(s"comOp=>a:${a},b:${b}")
     | a+b // 局部聚合
     | })

 如上,我发现当集合序列不是并行集合时,就不会去执行comOp函数部分的表达式。并且运算的结果和fold(10)的结果一样。

2,并行集合使用aggregate函数

当集合是并行集合时,调用aggregate函数后a的初始化值为aggregate(10)中的10。

并且,因为是并行集合,所以在使用sepOp函数中的表达式a+b时,a的值都是10,b的值从集合序列中选取;在使用comOp函数中的表达式时,a的初始化值为之前全局聚合时第一个分区内元素聚合后的结果,之后的每一次值都为comOp函数局部聚合后的结果。如下为集合List(1,2,3,4)转换成并行集合后调用aggregate函数时在两个聚合函数都使用了相加的过程中a和b的值(仅供参考):

接下来我使用代码来验证这种计算是否正确,如下: 

package aggregates
/**
 * @author:码到成龚
 * my motoo:"听闻少年二字,应与平庸相斥。"
 */
object Aggregate {
  def main(args: Array[String]): Unit = {
    val ar_im=Array(1,2,3,4)
    /**
    aggregate有合计的意思。
     *sepOp函数可以将每个分区的元素进行聚合,[全局聚合]
     然后用combine函数将每个分区的结果和初始值进行combine操作【局部聚合】
     (局部聚合加全局聚合)
     aggregate函数的第一个参数可以选择聚合之后的结果
     加上或者是减去的指定数值
     */
    val res=ar_im.par.aggregate(10)(
      (a,b)=>{
        println(s"sepOp => a:${a},b:${b}")
        a+b
      },
      (a,b)=>{
        println(s"comOp => a:${a},b:${b}")
        a+b
      }
    )
    println(res)
  }
}

 从上面的运行效果可知,计算结果是一样的,但是在comOp聚合函数那里会有些许的出入,不过我还是觉得按照自己的理解来比较方便些。如果知道aggregate函数处理并行集合时在comOp函数出的a和b的值为什么是运行后的结果的,欢迎在评论区留言。如果对以上的内容有任何不理解的也欢迎在评论区留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/43924.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyCharm+PyQT5之二第一个QT程序

Tools菜单或者右键打开external tools的 QTdesigner,如下图,在PyQt5中最常用的窗口有三种,即Main Window Widget Dialog, Main Window 也就是主窗口,他要为用户提供一个带有菜单栏、工具栏和状态栏的窗口。 Widget:通用窗口&#…

零基础入门金融风控之贷款违约预测挑战赛——简单实现

零基础入门金融风控之贷款违约预测挑战赛 赛题理解 赛题以金融风控中的个人信贷为背景,要求选手根据贷款申请人的数据信息预测其是否有违约的可能,以此判断是否通过此项贷款,这是一个典型的分类问题。通过这道赛题来引导大家了解金融风控中…

Linux中less和more的区别

总结下more和less的区别(less is more): 1、less可以按键盘上下方向键显示上下文内容,more不能通过上下方向键控制显示(但是可以用b实现向上翻页,空格键实现向下翻页) 2、less不必读整个文件,加载速度会比…

数码视讯Q5、Q7_晶晨S905L/M/M2_nandemmc通刷_完美精简线刷固件

数码视讯Q5、Q7_晶晨S905L/M/M2_nand&emmc通刷_完美精简线刷固件 固件特点: 1、修改dns,三网通用; 2、开放原厂固件屏蔽的市场安装和u盘安装apk; 3、无开机广告,无系统更新,不在被强制升级&#xf…

一道有趣的最长子序列问题

一道有趣的最长子序列问题 – 潘登同学的金融经济学笔记 文章目录一道有趣的最长子序列问题 -- 潘登同学的金融经济学笔记来源求解递推公式算法实现来源 前几天在刷视频的时候,发现了这样一道题 所谓子序列就是一个序列 ai1,ai2,⋯,aina_{i1},a_{i2},\cdots,a_{in}…

【5w字】SpringBoot源码分析

Spring Boot源码分析 文章目录Spring Boot源码分析启动类分析SpringBootConfigurationEnableAutoConfigurationComponentScanSpringBoot启动流程1. 准备SpringApplication获取当前 web 应用类型设置初始化器设置监听器推导主应用程序类2. Spring Boot的运行创建计时器并启动设置…

开源工具 | ASV-Subtools更新:runtime模块重磅发布

ASV-Subtools更新 - runtime模块重磅发布 - ASV-Subtools是厦门大学智能语音实验室(XMUSPEECH)于2020年6月推出的一套高效、易于扩展的声纹识别开源工具,该工具是基于Kaldi与Pytorch开发的,充分结合了Kaldi 在语音信号和后端处理…

Fe3+-多巴胺修饰Pluronic的多功能性水凝胶/多巴胺修饰聚丙烯微孔膜表面的研究

下面整理了Fe3-多巴胺修饰Pluronic的多功能性水凝胶/多巴胺修饰聚丙烯微孔膜表面,和小编一起来看! Fe3-多巴胺修饰Pluronic多功能性水凝胶 利用对硝基苯基氯酸甲酯作为聚合物Pluronic F127端羟基活化剂,与盐酸多巴胺直接反应制备末端多巴胺修饰的Pluron…

【web课程设计网页规划与设计】基于HTML+CSS+JavaScript火车票网上预订系统网站(4个页面)

🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (10…

Part4_场景_第52章 场景描述第53章 柏林I:BVG场景第54章 柏林II:CEMDAP-Matsim-Cadyts方案

第52章 场景概述 本书的最后一部分总结了MATSIM场景,如图52.1中的地图所示,并在http://matsim.org/scolutions中列出。 尽管存在基于免费和公共数据的真实场景,如圣地亚哥或科特布斯场景(第84或66章),但由于数据隐私问题,许多场景是不公开的。 然而,了解适用于情景创建…

【STM32备忘录】二、FSMC做LCD控制器,使用stm32cube配置示例

文章目录1. FSMC框图2. 配置示例(1) cube配置(2) 代码参考*疑问1. FSMC框图 如果屏幕接口8位数据宽度访问,地址线FSMC_A[25:0], 一共26位,一个块22667108864Byte64MB,如果屏幕接口16位数据宽度访问,地址线FSMC_A[25:0], 一共26位&…

远程访问数据库,快解析助力疫情防控远程办公

当前,国内疫情形势不容乐观,企业的经营发展再一次面临巨大挑战。虽然“远程办公”早已不是新鲜词,但依然有大量企业没有做好随时切换到远程办公的准备。如遇疫情风险,企业运营很容易陷入瘫痪。 企业一般在内网部署服务器、视频监…

【Java并发入门】01 并发编程Bug的源头

一、根本原因 「CPU、内存、磁盘之间的速度差异」 为了能同时执行多个任务,CPU 发展出时间片轮转、多核等CPU 要从内存中读数据太慢了,所以给自己设置了缓存CPU 读磁盘更慢了,所以可以让该线程阻塞 二、直接原因 缓存导致的可见性问题 C…

函数 function

一、创建函数方法 1.基本语法 函数是引用数据类型 1.1有函数名称的叫具名函数 function 函数名称&#xff08;&#xff09;{ }&#xff1b; 调用函数&#xff1a; 函数名&#xff08;&#xff09;&#xff1b; <script>function fnl( ){var a 2;var b 5…

教你快速搭建微服务环境

目录 一、项目搭建 1.父项目搭建 2.子项目的搭建 二、项目展示 一、项目搭建 1.父项目搭建 步骤&#xff1a; 1 选择maven项目作为父项目&#xff0c;修改为1.8之后直接点击next 2 定义父项目的名称&#xff0c;修改Artifct Coordinates ---> GroupId 然后点击finsh就可…

现代营销杂志现代营销杂志社现代营销编辑部2022年第11期目录

财务金融《现代营销》投稿&#xff1a;cnqikantg126.com 我国中小企业货币资金管理分析 安宁; 1-3 企业财务管理转型路径探讨 秦春; 4-6 互联网背景下电商企业税务风险研究 何秋梅; 7-9 目标成本管理在企业经济管理中的应用分析 艾蕾梅; 10-12 关于我国发展…

CentOS7.9集群部署(配置hosts、集群免密、时间同步)

在上一篇我们介绍了如何在windows下安装虚拟机&#xff0c;在虚拟机上安装CentOS7.9&#xff0c;并且在系统安装完成后配置了固定ip和系统时间。 在食用本篇之前&#xff0c;如果上述操作没有做过&#xff0c;可以先移步 windows安装VMware虚拟机(附带CentOS7部署) 但是在分布式…

文献阅读总结(3)Neural Graph Collaborative Filtering

1、Introduction 左图u1&#xff0c;右图从左图的u1开始展开 图反应的信息&#xff1a; 1、从路径u1->i2->u2,可以反映出u1和u2的相似性&#xff1b; 2、u1和i4之间有两条路径&#xff0c;而u1和i5之间只有一条路径&#xff0c;可以反应u1对i4的兴趣比u1对i5的兴趣更高…

[附源码]Python计算机毕业设计Django-Steam游戏平台系统论文

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【web网页设计期末课程大作业】基于HTML+CSS+JavaScript仿山东传媒职业学院网站

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…