Scala 第二篇 算子篇

Scala 第二篇 算子篇

上接:Scala 第一篇 基础篇

  • 一、数组方法
    • 1、数组的遍历
    • 2、数组获取元素
    • 3、数组排序
    • 4、交集,并集,补集
    • 5、集合转换操作
    • 6、合并,拆解,填充
    • 7、分组,排列
  • 二、算子
    • 1、简单计算
    • 2、高阶计算

一、数组方法

1、数组的遍历

val array = Array(1, 2, 3, 4, 5)val indices: Range = array.indices		// 提取下标区间
for (i <- indices) {println(array(i))					// 根据下标提取元素,注意是小括号
}for (i <- 0 until array.length) {		// 使用 until 遍历数组下标println(array(i))
}array.foreach(println)					// 使用 foreach 遍历数组元素val iter = array.iterator			// 正向迭代器
val reIter = array.reverseIterator	// 逆向迭代器
while (iter.hasNext) {println(iter.next())
}

2、数组获取元素

  1. 获取首尾元素

    val buffer = ArrayBuffer(1, 2, 3, 4)val head = buffer.head            // 第一个元素
    val opt1 = buffer.headOption      // 第一个元素
    val tail = buffer.tail            // 除第一个元素以外的其他元素
    // 剩余元素(阶梯) 4(1,2,3,4),3(2,3,4),2(3,4),1(4),0()
    val tails: Iterator[ArrayBuffer[Int]] = buffer.tailsval last = buffer.last            // 最后一个元素
    val opt2 = buffer.lastOption      // 最后一个元素
    val init = buffer.init    // 除最后一个元素以外的其他元素
    val inits = buffer.inits  // 剩余元素(阶梯) 4(1,2,3,4),3(1,2,3),2(1,2),1(1),0()
    
  2. 获取满足条件连续长度和元素

    val size1 = buffer.prefixLength(e => e < 3)     // 从集合的开头满足条件元素数量
    val size2 = buffer.segmentLength(e => e > 1, 1) //从 from 下标的连续满足条件元素数量val buf1 = buffer.take(1)         // 从集合的开头开始获取指定数量的元素。
    val buf2 = buffer.takeRight(2)    // 从集合的末尾开始获取指定数量的元素。
    val buf3 = buffer.takeWhile(e => e < 3)  // 从集合的开头开始获取连续满足条件的元素。
    

3、数组排序

  1. sortedsortBysortWith

    val buffer = ArrayBuffer((5, 2), (2, 5), (3, 2), (2, 4))val sort1 = buffer.sorted           // 默认按第一个值升序,如果第一个值相等按第二个值升序,如果有第三个值同理val sort2 = buffer.sortBy(_._2)     // 指定排序值,按第二个值排序(默认升序)// sortWith 定义元素之间的比较规则
    // 如果第一个值不相等按第一个值降序,否则按第二个值降序
    val sort3 = buffer.sortWith((a, b) => (if(a._1 != b._1) a._1 > b._1else a._2 > b._2
    ))
    
  2. 隐式函数 (不建议)

    val buffer = ArrayBuffer((5, 2), (2, 5), (3, 2), (2, 4))
    implicit val orderingTp2: Ordering[(Int, Int)] = Ordering.by(_._2) // 按第二个值
    val sort5 = buffer.sorted          // 按第二个值升序
    

4、交集,并集,补集

// 结果类型:前(左)置确定val buffer = ArrayBuffer(1, 2, 3, 4, 5)
val seq = Seq(3, 4, 5, 6, 7)// 交集
val intersect: ArrayBuffer[Int] = buffer.intersect(seq)
println("交集:" + intersect.mkString(", "))// 并集
val union: ArrayBuffer[Int] = buffer.union(seq)
println("并集:" + union.mkString(", "))// 差集
val diff: ArrayBuffer[Int] = buffer.diff(seq)
println("差集:" + diff.mkString(", "))

输出:

交集:3, 4, 5
并集:1, 2, 3, 4, 5, 3, 4, 5, 6, 7
差集:1, 2

补充:

// 连接字符串
val str0: String = buffer.mkString
val str1: String = buffer.mkString(sep:String)		// 指定分割符
val str2: String = buffer.mkString(start:String,sep:String,end:String)	// 指定,连接字符串的起始部分,分隔符,结束部分

5、集合转换操作

  1. 一个维度的转变

    import scala.collection.mutable.ArrayBufferval buffer = ArrayBuffer(1, 2, 3, 4, 5)
    // 正向差异类型转变,(将数字x映射为x*2并转化为字符串)
    val doubledBuffer: ArrayBuffer[String] = buffer.map(x => (x * 2).toString)
    // 正向同类型转变
    val squaredBuffer: ArrayBuffer[Int] = buffer.transform(x => x * x)
    // 逆向转变
    val reversedSquaredBuffer: ArrayBuffer[Int] = buffer.reverseMap(x => x * x)
    
  2. 二维变换

    import scala.collection.mutable.ArrayBufferval buffer2D = ArrayBuffer(ArrayBuffer(1, 2, 3),ArrayBuffer(4, 5, 6),ArrayBuffer(7, 8, 9)
    )
    // 使用 flatMap 将二维转换为一维,并对值做映射 (*2)
    val flatBuffer: ArrayBuffer[Int] = buffer2D.flatMap(_.map(_ * 2))
    // 使用 flatten 将二维转换为一维
    val flattenedBuffer: ArrayBuffer[Int] = buffer2D.flatten
    // 使用 transpose 进行二维数组缓冲区转置
    val transpose: ArrayBuffer[ArrayBuffer[Int]] = buffer2D.transpose
    
  3. 类型变换

    import scala.collection.mutable
    import scala.collection.parallel.mutable.ParArrayval buffer = mutable.Buffer(1, 2, 2, 3, 4, 5)
    val buffer_tp2 = mutable.Buffer((1, "a"), (2, "b"), (3, "c"))val mutableBuffer: mutable.Buffer[Int] = buffer.toBuffer // 转换为可变的,为了增删
    val array: Array[Int] = buffer.toArray                   // 转换为数组,(下标,排序)
    val parArray: ParArray[Int] = buffer.toParArray          // 转换为并行数组,分布式计算
    val map: Map[Int, String] = buffer_tp2.toMap             // 转换为 Map,键值映射
    val set: Set[Int] = buffer.toSet                         // 转换为集合(去重)
    

6、合并,拆解,填充

import scala.collection.mutable.ArrayBufferval buffer1 = ArrayBuffer('a', 'b', 'c', 'd')
val buffer2 = ArrayBuffer(1, 2, 3)// 最短原则合并,结果:(a,1), (b,2), (c,3)
val zippedShortest: ArrayBuffer[(Char, Int)] = buffer1.zip(buffer2)
// 最长原则合并,长度不够填充默认值,结果:(a,1), (b,2), (c,3), (d,0)
val zippedAll: ArrayBuffer[(Char, Int)] = buffer1.zipAll(buffer2, 'x', 0)
// 带索引合并
val zippedWithIndex: ArrayBuffer[(Char, Int)] = buffer1.zipWithIndex
// 拆解操作,拆解二元组,拆解三元组为unzip3
val (unzipped1, unzipped2): (ArrayBuffer[Char], ArrayBuffer[Int]) = zippedShortest.unzip
// 填充操作,不足6为填充: '_'
val paddedBuffer: ArrayBuffer[Char] = buffer1.padTo(6, '_')// 输出结果
println("最短原则合并:" + zippedShortest)
println("最长原则合并:" + zippedAll)
println("带索引合并:" + zippedWithIndex)
println("拆解结果:" + unzipped1 + ", " + unzipped2)
println("填充后的数组:" + paddedBuffer)

输出:

最短原则合并:ArrayBuffer((a,1), (b,2), (c,3))
最长原则合并:ArrayBuffer((a,1), (b,2), (c,3), (d,0))
带索引合并:ArrayBuffer((a,0), (b,1), (c,2), (d,3))
拆解结果:ArrayBuffer(a, b, c), ArrayBuffer(1, 2, 3)
填充后的数组:ArrayBuffer(a, b, c, d, _, _)

7、分组,排列

import scala.collection.mutable.ArrayBuffer                                                      val buffer = ArrayBuffer(1, 2, 3, 4, 5)                                                          // 切片操作,提取下标为1开始4结束的元素(包头不包尾)                                                                 
val bufferSlice: ArrayBuffer[Int] = buffer.slice(1, 4)
// 滑动窗口操作,固定大小为 2 的滑动窗口,并且每次滑动 1 个元素。
val itAB: Iterator[ArrayBuffer[Int]] = buffer.sliding(2, 1)  //                                    
// 分组操作                                                                                          
val itGrouped: Iterator[ArrayBuffer[Int]] = buffer.grouped(2)	// 定长分组
val map: Map[Int, ArrayBuffer[Int]] = buffer.groupBy(_ % 2) 	// 按键分组
val tp2: (ArrayBuffer[Int], ArrayBuffer[Int]) = buffer.partition(_ < 4)	// 2 分区,按要求(小于4)分为两类
val splits: (ArrayBuffer[Int], ArrayBuffer[Int]) = buffer.splitAt(2)	// 2 分区,在索引位置2处分成两部分
// grouped(size) <=> sliding(size,size),两者等价val itPermutations: Iterator[ArrayBuffer[Int]] = buffer.permutations	// 全排列  
val itCombinations: Iterator[ArrayBuffer[Int]] = buffer.combinations(2) // 组合排列

二、算子

1、简单计算

  1. 数组元素为数值类型可以直接计算

    import scala.collection.mutable.ArrayBuffer
    val buffer = ArrayBuffer(1, 2, 3, 4, 5)
    val sum = buffer.sum
    val max = buffer.max
    val min = buffer.min
    val pro = buffer.product	// 阶乘
    
  2. 非数值元素类型

    val buffer = ArrayBuffer(("aaa", 3), ("bbb", 1), ("ccc", 2), ("aaa", 2))
    val sum = buffer2.map(e => e._2).sum
    val max: (String, Int) = buffer2.maxBy(e => e._2)
    val min: (String, Int) = buffer2.minBy(e => e._2)
    val cnt = buffer2.count(e => e._2 < 2)
    
  3. 计算优化:并行序列,并行计算

    并行数组 ParArray[T],它是一个并行版本的数组,允许在多个线程上并行地操作数组元素。这对于对大型数据集进行处理或利用多核处理器进行并行计算非常有用,可以提高处理效率。

    val par: ParArray[T] = buffer.par
    

2、高阶计算

  1. 简介
    • 聚合操作
    • aggregate 方法对数组进行聚合操作,指定一个初始值 o: O,一个用于映射元素的函数 map: (O, T) => O,和一个用于合并两个结果的函数 red: (O, O) => O。这个操作会将数组元素映射为结果。在并行计算中使用这个操作,直接调用并行数组的 par.aggregate 方法。
    • 折叠操作
    • fold 方法对数组进行折叠,指定一个初始值 init: O,和一个用于合并两个结果的函数 func: (O, O) => O。这个操作会从数组的一端开始,逐个将元素与初始值进行合并,直到折叠到另一端。通过指定 LeftRight 来指定折叠的方向。
    • 扫描操作
    • scan 方法对数组进行扫描,指定一个初始值 init: O,和一个用于合并两个结果的函数 f: (O, O) => O。这个操作会从数组的一端开始,逐个将元素与初始值进行合并,并在每一步生成一个过程结果。最终结果是一个包含所有过程结果的数组缓冲区。
    • 归约操作
    • reduce 方法对数组进行归约操作,指定一个用于合并两个结果的函数 f: (O, O) => O。这个操作会从数组的一端开始,逐个将元素进行合并,直到最终只剩下一个结果为止。通过指定 LeftRight 来指定归约的方向。
    // 聚合操作
    val rst:O = buffer.aggregate(o:O)(map:(O,T)=>O,red:(O,O)=>O)
    val rst:O = par.aggregate(o:O)(map:(O,T)=>O,red:(O,O)=>O)		// 并行 Map & Red
    // 双向折叠操作
    val rst:O = buffer.fold[Left|Right](init:O)(func:(O,O)=>O)
    // 过程结果扫描操作
    val rst:ArrayBuffer[O] = buffer.scan[Left|Right](init:O)(f:(O,O)=>O)
    // 归约操作
    val rst:O = buffer.reduce[Left|Right](f:(O,O)=>O)
    
  2. 案例

    1、aggregate 案例

    val buffer = ArrayBuffer(1, 2, 3, 4)val map = (a:Int,b:Int) => {println(s"MAP $a + $b = ${a+b}")a + b
    }
    val reduce = (a:Int,b:Int) => {println(s"RED $a + $b = ${a+b}")a + b
    }
    val rst: Int = buffer.par.aggregate(0)(map,reduce)
    

    输出:

    MAP 0 + 2 = 2
    MAP 0 + 1 = 1
    MAP 0 + 4 = 4
    MAP 0 + 3 = 3
    RED 1 + 2 = 3
    RED 3 + 4 = 7
    RED 3 + 7 = 10
    

    2、fold 案例

    val buffer = ArrayBuffer(1, 2, 3)
    val add = (a:Int, b:Int) => {println(s"$a + $b = ${a+b}")a + b
    }
    val rst: Int = buffer.fold(0)(add)
    println("-------------------------")
    val rst: Int = buffer.foldRight(0)(add)
    

    输出:

    0 + 1 = 1
    1 + 2 = 3
    3 + 3 = 6
    -------------------------
    3 + 0 = 3
    2 + 3 = 5
    1 + 5 = 6
    

    3、scan 案例

    val buffer = ArrayBuffer(1, 2, 3, 4)
    val add = (a: Int, b: Int) => {println(s"$a + $b = ${a + b}")a + b
    }
    val rst1: ArrayBuffer[Int] = buffer.scan(0)(add)
    println(rst1)val rst2: ArrayBuffer[Int] = buffer.scanRight(0)(add)
    println(rst2)
    

    输出:

    0 + 1 = 1
    1 + 2 = 3
    3 + 3 = 6
    6 + 4 = 10
    ArrayBuffer(0, 1, 3, 6, 10)
    4 + 0 = 4
    3 + 4 = 7
    2 + 7 = 9
    1 + 9 = 10
    ArrayBuffer(10, 9, 7, 4, 0)
    

    4、reduce 案例

    val buffer = ArrayBuffer(1, 2, 3, 4)
    val add = (a: Int, b: Int) => {println(s"$a + $b = ${a + b}")a + b
    }
    val rst1: Int = buffer.reduce(add)
    println("-------------------------")
    val rst2: Int = buffer.reduceRight(add)
    

    输出:

    1 + 2 = 3
    3 + 3 = 6
    6 + 4 = 10
    -------------------------
    3 + 4 = 7
    2 + 7 = 9
    1 + 9 = 10
    
  3. 简单优化
    1. sizeHint(size: Int):这个重载形式接收一个整数参数 size,表示预期添加的元素数量。调用这个方法后,缓冲区的实现可能会调整内部数据结构的大小以适应更大的元素数量,从而提高性能。这对于在添加大量元素之前知道预期大小的情况很有用。
    2. sizeHint(data: TraversableLike[T]):这个重载形式接收一个 TraversableLike[T] 类型的参数 data,表示另一个集合,它的大小可以作为预期添加的元素数量的提示。调用这个方法后,缓冲区的实现可能会根据给定集合的大小来调整内部数据结构的大小,以适应更大的元素数量。
    3. sizeHintBounded(size: Int, data: TraversableLike[T]):这个重载形式接收两个参数:一个整数 size 和一个 TraversableLike[T] 类型的参数 data。它表示给定集合的大小和另一个预期添加的元素数量。调用这个方法后,缓冲区的实现可能会根据这两个参数来调整内部数据结构的大小,以适应更大的元素数量。
    // 给出预期添加元素数量的提示,用于优化构建器的性能
    buffer.sizeHint(size:Int)
    buffer.sizeHint(data:TraversableLike[T])
    buffer.sizeHintBounded(size:int,data:TraversableLike[T])
    

下接:Scala 第三篇 OOP篇
待更新

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

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

相关文章

IDEA2024配置RunDashBoard(Services)面板

IDEA2024配置RunDashBoard(Services)面板 新版本的IDEA没有RunDashBoard&#xff0c;取而代之的是Services面板&#xff0c;不需要配置workspace.xml文件; 本文教你简单的方法就能一个SpringBoot的Main运行多次&#xff0c;方便调试。 1、配置启动类 导航栏&#xff0c;Edit…

SiteMesh介绍

SiteMesh介绍 SiteMesh是一个网页布局和修饰的框架&#xff0c;利用它可以将网页的内容和页面结构分离&#xff0c;以达到页面结构共享的目的。 下载和安装SiteMesh 官方下载地址&#xff1a;http://www.opensymphony.com/sitemesh/download.action 配置过滤器 在web.xml中…

使用立创EDA打开JSON格式的PCB及原理图

一、将PCB和原理图放同一文件夹 并打包成.zip文件 二、打开嘉立创EDA并导入.zip文件 文件 -> 导入 -> 嘉立创EDA标准版/专业版 三、选择.zip文件并选择 “导入文件并提取库” 四、自定义工程路径 完成导入并转换为.eprj文件 五、视频教学 bilibili_使用立创EDA打开JSO…

Pytorch入门实战: 06-VGG-16算法-Pytorch实现人脸识别

第P6周&#xff1a;VGG-16算法-Pytorch实现人脸识别 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 &#x1f3e1; 我的环境&#xff1a; 语言环境&#xff1a;Python3.8 编译器&#xff1a;Jupyter La…

linux部署dagu和benthos作为调度平台+数据处理框架

准备文件 dagu和benthos下载地址(根据版本自行修改) dagu: https://github.com/dagu-dev/dagu/releases/download/v1.12.11/dagu_1.12.11_linux_amd64.tar.gz benthos: https://github.com/benthosdev/benthos/releases/download/v4.26.0/benthos_4.26.0_linux_amd64.tar.gz …

Rest接口/Nginx日志记录和采集

文章目录 一、Rest接口日志二、Nginx日志三、采集日志四、夜莺查看Nginx日志五、夜莺查看Rest接口日志 一、Rest接口日志 记录日志字典定义 接口URL接口名称,类别,入参全记录,出参全记录,入参字段1:中文名1/入参字段2:中文名2,出参字段1:中文名1/test/api/login账户登录,登录…

Redis 逻辑过期策略设计思路

引言&#xff1a; 当我们平常使用Redis缓存的时候&#xff0c;会出现一种场景&#xff0c; redis的key到过期时间了&#xff0c;总是需要到数据库里面去查一遍数据再set回redis&#xff0c;这个时候如果数据库响应比较慢&#xff0c;那么就会造成用户等待&#xff0c;如果刚好…

09 JavaScript学习:对象

对象的概念 在计算机科学中&#xff0c;对象是一种数据结构&#xff0c;用于存储数据和方法&#xff08;也称为函数&#xff09;。对象可以包含属性&#xff08;也称为成员变量&#xff09;和方法&#xff08;也称为成员函数&#xff09;&#xff0c;通过这些属性和方法可以描述…

【微信小程序】解决分页this.setData数据量太大的限制问题

1、原始方法&#xff0c;每请求一页都拿到之前的数据concat一下后整体再setData loadData() {let that thislet data {}data.page this.data.pagedata.size this.data.sizefindAll(data).then(res > {if (res.data.code 1) {this.setData({dataList: this.data.dataLi…

android开发 多进程的基本了解

目录 如何开启多进程?理解多进程模式的运行机制 如何开启多进程? 给四大组件在androidMenifest中指定android:precess <activityandroid:name".ThreeActivity"android:exported"false"android:process"com.my.process.three.remote" />…

如何查询下载自然资源相关的法律法规

自然资源部门户网站- 政策法规库 (https://f.mnr.gov.cn/) 以查询下载“节约用水条例”为例&#xff1a;输入标题&#xff0c;点击检索&#xff0c;出现对应的检索结果&#xff1a; 打开详细&#xff0c;可以看到节约用水条例的详细内容&#xff1a; 点击文后的打印或者下载&a…

如何使用PHPStudy+Cloudreve搭建个人云盘并实现无公网IP远程访问——“cpolar内网穿透”

文章目录 1、前言2、本地网站搭建2.1 环境使用2.2 支持组件选择2.3 网页安装2.4 测试和使用2.5 问题解决 3、本地网页发布3.1 cpolar云端设置3.2 cpolar本地设置 4、公网访问测试5、结语 1、前言 自云存储概念兴起已经有段时间了&#xff0c;各互联网大厂也纷纷加入战局&#…

python爬虫开发能力需要哪些

Python爬虫开发能力需要以下几个方面的知识和技能&#xff1a; Python基础&#xff1a;你需要熟悉Python的语法和编程基础&#xff0c;包括变量、数据类型、控制结构、函数、模块等。此外&#xff0c;了解Python面向对象编程的概念和实践也是很有帮助的。网络编程&#xff1a;…

day48_servlet

今日内容 周一 0 复习上周 1 本周计划 2 MVC和三层架构 3 Login案例 4 请求转发 5 重定向 0 复习昨日 1 jdbc五大步骤 注册驱动(反射)获得连接获得执行sql对象执行SQL关流 2 什么是SQL注入 通过SQL关键词,在执行SQL时出现不正常的情况 3 PreparedStatement怎么使用,有什么特点 …

刷题之Leetcode19题(超级详细)

19.删除链表的倒数第N个节点 力扣题目链接(opens new window)https://leetcode.cn/problems/remove-nth-node-from-end-of-list/ 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 进阶&#xff1a;你能尝试使用一趟扫描实现吗&#x…

react09 hooks(useState)

react-09 hooks&#xff08;useState&#xff09; hooks组件&#xff08;函数组件动态化&#xff09; 其本质就是函数组件&#xff0c;引用一些hooks方法&#xff0c;用来在函数组件中进行例如状态管理&#xff0c;模拟类组件的生命周期等&#xff0c;只能运用到函数组件中 ho…

代码随想录算法训练营第三十二天|122.买卖股票的最佳时机II,55. 跳跃游戏,45.跳跃游戏II

目录 122.买卖股票的最佳时机II思路代码 55. 跳跃游戏思路代码 45.跳跃游戏II思路代码 122.买卖股票的最佳时机II 题目链接&#xff1a;122.买卖股票的最佳时机II 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a;贪心算法也能解决股票问题&#xff01;LeetCode&#xff1…

项目管理-项目成本管理

目录 一、成本管理概述 二、成本估算 2.1 定义 2.2 成本估算方法 2.2.1 自顶向下的估算 2.2.1.1 估算方法 2.2.1.2 优点 2.2.1.3 缺点 2.2.2 自底向上的估算 2.2.2.1 估算方法 2.2.2.2 优点 2.2.2.3 缺点 2.2.3 差别估算法 三、成本预算 3.1 定义 3.2 成本预算的…

使用 optimum 使得 embedding 生成速度提高 5 倍(和原生 sentence transformer 模型对比)

今天偶然刷到了 Accelerate Sentence Transformers with Hugging Face Optimum (philschmid.de) 看到可以是用 optimum 调用 onnx API 加速 embedding 模型在 CPU 上的推理速度&#xff0c;而且相比之前&#xff1a; 使用 onnx 使得 embedding 生成速度提高 4 倍&#xff08…

ccfcsp201312-2 ISBN号码

注意&#xff1a;50分 -- u10&#xff0c;最后一位为X 代码&#xff1a; #include <bits/stdc.h> using namespace std; string s; int a[12]; int main() {cin >> s;a[1] s[0] - 0;a[2] s[2] - 0;a[3] s[3] - 0;a[4] s[4] - 0;a[5] s[6] - 0;a[6] s[7] - …