Scala中Array的算子记录

本文详细介绍了Scala中数组的各种操作方法,包括元素提取、修改、分组、聚合等,并提供了丰富的示例代码来帮助读者理解和掌握这些操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提取元素

All:

val v: T = arr.head													//提取第一个元素
val v: Option[T] = arr.headOption									//提取第一个元素
val v: Int = arr.last												//提取最后一个元素
val v: Option[T] = arr.lastOption									//提取最后一个元素
val v: T = arr(index:Int)											//提取指定下标位置元素
val v: T = arr.apply(0)												//提取指定下标位置元素
val v: T = arr.applyOrElse(index:Int,{_:Int=>value:T})				//接收2个参数,参数1是调用的参数,参数2是回调函数,如果参数1调用的参数匹配,返回匹配的值,否则调用回调函数。
val v: Array[T] = arr.take(size:Int)								//从左边取size个元素
val v: Array[T] = arr.takeRight(size:Int)							//从右边取size个元素
val v: Array[T] = arr.takeWhile(p:T=>Boolean)						//从下标0开始取,碰到不满足条件p的就结束
val v: Array[T] = arr.filter(p:T=>Boolean)							//提取满足条件p的所有元素
val v: Array[T] = arr.filterNot(p:T=>Boolean)						//提取不满足条件p的所有元素
val v: Array[T] = arr.collect(pf:PartialFunction[T,B]{T=>B})		//提取所有满足偏函数pf的元素
val v: Option[T] = arr.collectFirst(pf:PartialFunction[T,B]{T=>B})	//提取满足偏函数pf的第一个Option元素
val v: Option[T] = arr.find(p:T=>Boolean)							//提取第一个满足偏函数的元素
val v: Array[T] = arr.slice(from:Int,until:Int)						//提取从from到until的元素(不包含until)
val v: Array[T] = arr.init											//提取除了最后一个元素以外的元素
val v: Array[T] = arr.tail											//提取除了第一个元素以外的元素
val v: Iterator[Array[T]] = arr.inits								//递归提取除了最后一个元素以外的元素
val v: Iterator[Array[T]] = arr.tails								//递归提取除了第一个元素以外的元素
val v: Option[T] = arr.lift(index:Int)								//提取指定下标位置的Option元素
val v: PartialFunction[T,T] = arr.orElse(pf:PartialFunction[T,B])	//下标越界根据偏函数规则提取元素,否则直接提取下标元素

详解:

applyOrElse

接收2个参数,参数1是调用的参数,参数2是回调函数,如果参数1调用的参数匹配,返回匹配的值,否则调用回调函数。

val arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val arrChar: Array[Char] = Array('a', 'b', 'c')
//参数1匹配
val v1: Int = arr.applyOrElse(1, { _: Int => 0 })
val v2: Char = arrChar.applyOrElse(1, {_:Int => 'z'})
println(v1)	// 2
println(v2)	// b

//参数1不匹配
val v1: Int = arr.applyOrElse(11, { _: Int => 0 })
val v2: Char = arrChar.applyOrElse(3, {_:Int => 'z'})
println(v1)	// 0
println(v2)	// z	

takeWhile

从下标0开始取,碰到不满足条件p的就结束

val arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
var arrReverse: Array[Int] = Array(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
val array: Array[Int] = arr.takeWhile(_<5)
val array1: Array[Int] = arrReverse.takeWhile(_ <5)
array.foreach(print);println()
println("--------------")
array1.foreach(print)

//结果:
1234
--------------
		//空行没数据

collect&collectFirst

collect:提取所有满足偏函数pf的元素

collectFirst:提取满足偏函数pf的第一个Option元素

val arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val v: Array[Int] = arr.collect({ case x if (x % 2 == 0) => x })
v.foreach(print)	//246810

val v: Option[Int] = arr.collectFirst({ case x if (x % 2 == 0) => x })
println(v)			//Some(2)

//偏函数:pf
//偶数不变,奇数变0
val pf:PartialFunction[Int,Int]={
    case x if x%2==0 => x
    case x if x%2!=0 => 0
}
val v: Array[Int] = arr.collect(pf)
v.foreach(print)	//02040608010

inits&tailas

inits:递归提取除了最后一个元素以外的元素

tails:递归提取除了第一个元素以外的元素

val arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val v: Iterator[Array[Int]] = arr.inits
v.foreach(x=>{
    x.foreach(print)
    println()
})
//============
12345678910
123456789
12345678
1234567
123456
12345
1234
123
12
1


val v: Iterator[Array[Int]] = arr.tails
v.foreach(x=>{
    x.foreach(print)
    println()
})
//============
12345678910
2345678910
345678910
45678910
5678910
678910
78910
8910
910
10

orElse

下标越界根据偏函数规则提取元素,否则直接提取下标元素

val arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

val p:PartialFunction[Int,Int] = (x:Int)=>x match {
    case x if(x%2==0) => x
    case _ => -1
}

val v: PartialFunction[Int, Int] = arr.orElse(p)
println(v(0))   // 1
println(v(1))   // 2
println(v(10))  // 10
println(v(11))  // -1

修改元素

val v:Unit = arr.update(index:Int, newValue:T)							//修改指定index下标元素为newValue
val v: Array[T] = arr.updated(index:Int, newValue:T)					//修改指定index下标元素为newValue,并生成新的数组返回
val v: Array[T] = arr ++/union sub										//并集
val v: Array[T] = arr intersect sub										//交集
val v: Array[T] = arr diff sub											//差集
val v: Array[T] = arr :+ elem											//尾部追加
val v: Array[T] = elem +: arr											//头部追加
val v: Array[T] = arr.drop(size:Int)									//删除头部size个元素
val v: Array[T] = arr.dropRight(size:Int)								//删除尾部size个元素
val v: Array[T] = arr.dropWhile(p:T=>Boolean)							//从左到右删除符合条件p的元素,碰到第一个不符合条件的元素停止
val v: Array[T] = arr.patch(from:Int,sub:GenSeq, replaceLen:Int)		//从from开始的replaceLen个元素替换为sub中的全部元素

逐个迭代处理

val v: Array[B] = arr.map(f:T=>B)										//对元素做f定义的操作,可以转变数据类型
val v: mutable.WrappedArray[T] = arr.transform(f:T)						//对元素做f定义的操作,不可以转变数据类型
val v: Array[B] = arr.reverseMap(f:T=>B)								//map+逆序
val v: Array[T] = arr.flatten											//多维数组降一个维度
val v: Array[T] = arr.flatMap(f:T=>B)									//map+flatten

分组

All:

val v: ParArray[T] = arr.par											//分组并行
val v: (Array[T], Array[T]) = arr.partition(p:T=>Boolean)				//根据条件p分区
val v: Map[K, Array[T]] = arr.groupBy(key:K)							//根据key分组
val v: Iterator[Array[T]] = arr.grouped(size:Int)						//按指定size个数分组
val v: Iterator[Array[T]] = arr.sliding(size:Int[,step:Int default 1])	//从第一个元素开始,每个元素和它后面的 size - 1 个元素组成一个数组

详解:

sliding

sliding(size: Int)

从第一个元素开始,每个元素和它后面的 size - 1 个元素组成一个数组,最终组成一个新的集合返回,当剩余元素不够 size 数,则停止

var arr = Array(1,2,3,4,5,6,7,8,9)
arr.sliding(3).foreach(arr=>{
    arr.foreach(i=>print(s"${i}\t"))
    println()
})
println("=============")
arr.sliding(4).foreach(arr=>{
    arr.foreach(i=>print(s"${i}\t"))
    println()
})

//结果:
1	2	3	
2	3	4	
3	4	5	
4	5	6	
5	6	7	
6	7	8	
7	8	9	
=============
1	2	3	4	
2	3	4	5	
3	4	5	6	
4	5	6	7	
5	6	7	8	
6	7	8	9

sliding(size: Int, step: Int)

从第一个元素开始,每个元素和它后面的 size - 1 个元素组成一个数组,最终组成一个新的集合返回,当剩余元素不够 size 数,则停止,该方法,可以设置步进 step,第一个元素组合完后,下一个从 上一个元素位置+step后的位置处的元素开始

var arr = Array(1,2,3,4,5,6,7,8,9)
arr.sliding(3,1).foreach(arr=>{
     arr.foreach(i=>print(s"${i}\t"))
     println()
 })
println("==============")
arr.sliding(3,3).foreach(arr=>{
    arr.foreach(i=>print(s"${i}\t"))
    println()
})

//结果:
1	2	3	
2	3	4	
3	4	5	
4	5	6	
5	6	7	
6	7	8	
7	8	9	
==============
1	2	3	
4	5	6	
7	8	9	

聚合

All:

val v: T = arr.reduce(f:(T,T)=>T)											//从左向右对元素按f指定的操作进行聚合
val v: T = arr.reduceLeft(f:(T,T)=>T)										//从左向右对元素按f指定的操作进行聚合
val v: T = arr.reduceLeftOption(f:(T,T)=>T)									//从左向右对元素按f指定的操作进行聚合
val v: T = arr.reduceRight(f:(T,T)=>T)										//从右向左对元素按f指定的操作进行聚合
val v: T = arr.reduceRightOption(f:(T,T)=>T)								//从右向左对元素按f指定的操作进行聚合
val v: T = arr.fold[Left](beginValue:T)(f:(T,T)=>T)							//从左向右根据定的初始值beginVlaue再对数组执行f指定的操作
val v: T = arr.foldRight(beginValue:T)(f:(T,T)=>T)							//从右向左根据定的初始值beginVlaue再对数组执行f指定的操作
val v: Array[T] = arr.scan[left](beginValue:T)(f:(T,T)=>T)					//从左向右根据定的初始值beginVlaue再对数组执行f指定的操作,返回每一步操作产生数据的数组
val v: Array[T] = arr.scanRight(beginValue:T)(f:(T,T)=>T)					//从右向左根据定的初始值beginVlaue再对数组执行f指定的操作,返回每一步操作产生数据的数组
val v: T = arr.aggregate(beginValue:B)(map(B,T)=>B,reduce:(B,B)=>B)			//根据定的初始值beginVlaue再对数组执行map和reduce

val v: T = arr.sum															//求和
val v: Int = arr.count(p:Int=>Bollean)										//根据p的条件计数
val v: T = arr.min															//最小值
val v: T = arr.max															//最大值
val v: Int = arr.minBy(_.?) => T:Tuple | Class								//最小
val v: Int = arr.maxBy(_.?) => T:Tuple | Class								//最大

详解:

reduce[Left][Option]/reduce[Right][Option]

//从左向右
val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
println(arr.reduce(_ + _))
//结果
45

//内部过程
val add=(x:Int,y:Int)=>{
    println(s"${x}+${y}=${x+y}")
    x+y
}
println(arr.reduce(add))
//===================
1+2=3
3+3=6
6+4=10
10+5=15
15+6=21
21+7=28
28+8=36
36+9=45
45

//left/leftOption
val value:B = reduceLeft(f:(T,T)=>B)
val value:B = reduceLeftOption(f:(T,T)=>B)



//从右向左
println(arr.reduceRight(_ + _))
//内部过程
val add=(x:Int,y:Int)=>{
    println(s"${x}+${y}=${x+y}")
    x+y
}
println(arr.reduceRight(add))
//===================
8+9=17
7+17=24
6+24=30
5+30=35
4+35=39
3+39=42
2+42=44
1+44=45
45
//right/rightOption
val value:B = reduceRight(f:(T,T)=>B)
val value:B = reduceRightOption(f:(T,T)=>B)

fold & foldleft & foldright

fold:初始值顺序和每个元素运算,把得到的结果与下一个元素进行运算

foldleft:和fold一样,从左往右,初始值顺序和每个元素运算,把得到的结果与下一个元素进行运算

foldright:从左往右,初始值顺序和每个元素运算,把得到的结果与下一个元素进行运算

val cal = (a:Int,b:Int)=>{    println(s"${a}-${b}=${a-b}")    a-b}println(arr.fold(0)(cal))println("-----------")println(arr.foldLeft(0)(cal))println("-----------")println(arr.foldRight(0)(cal))//结果:0-1=-1-1-2=-3-3-3=-6-6-4=-10-10-5=-15-15-6=-21-21-7=-28-28-8=-36-36-9=-45-45-----------0-1=-1-1-2=-3-3-3=-6-6-4=-10-10-5=-15-15-6=-21-21-7=-28-28-8=-36-36-9=-45-45-----------9-0=98-9=-17--1=86-8=-25--2=74-7=-33--3=62-6=-41--4=55

sacn[Left/Right]

用法同 fold,scan会把每一步的计算结果放到一个新的集合中返回,而 fold 返回的是单一的值

arr.scan(0)(cal).foreach(println)arr.scanLeft(0)(cal).foreach(println)arr.scanRight(0)(cal).foreach(println)

aggregate

聚合计算,aggregate是柯里化方法,参数是两个方法,为了方便理解,我们把aggregate的两个参数,分别封装成两个方法,并把计算过程打印出来。

def main(args: Array[String]) {
    val a = List(1,2,3,4)
    val c = a.par.aggregate(5)(seqno,combine)
    println("c:"+c)
}
def seqno(m:Int,n:Int): Int ={
    val s = "seq_exp=%d+%d"
    println(s.format(m,n))
    return m+n
}
def combine(m:Int,n:Int): Int ={
    val s = "com_exp=%d+%d"
    println(s.format(m,n))
    return m+n
}
/**
    seq_exp=5+3
    seq_exp=5+2
    seq_exp=5+4
    seq_exp=5+1
    com_exp=6+7
    com_exp=8+9
    com_exp=13+17
    c:30
*/

验证

val v: Boolean = arr.isEmpty												//判断是否为空
val v: Boolean = arr.nonEmpty												//判断是否非空
val v: Boolean = arr.exists(p:T=>Boolean)									//是否存在符合条件p的元素
val v: Boolean = arr.contains(elem:T)										//是否存在给定元素
val v: Boolean = arr.containsSlice(sub:GenSeq)								//是否存在完整的子串
val v: Boolean = arr.forall(p:T=>Boolean)									//是否所有元素都符合条件p
val v: Boolean = arr.corresponds(sub:GenSeq)(p:T=>Boolean)					//是否sub中所有元素和主集合的元素满足关系p
val v: Boolean = arr.sameElements(sub:GenSeq)								//集合和子集是否拥有相同元素
val v: Boolean = arr.startsWith(sub:GenSeq)									//集合是否以sub开头
val v: Boolean = arr.endWith(sub:GenSeq)									//集合是否以sub结尾

长度

val v: Int = arr.length/Size												//求集合长度
val v: Int = arr.prefixLength(p:T=>Boolean)									//从左开始,连续满足条件p的连续元素长度
val v: Int = arr.segmentLength(p:T=>Boolean,index:Int)						//从指定下标位置index开始,连续满足条件p的元素长度
val v: Int = arr.lengthCompare(len:Int)										//返回集合长度和给定长度len的差值

转变

All:

arr.copyToArray(copy)														//将arr中的元素复制到copy中,长度有限制
arr.copyToBuffer(copy)														//将arr中的元素复制到copy中,长度无限制
val v: Array[T] = arr.toArray												//将arr转化为Array数组
val v: mutable.Buffer[T] = arr.toBuffer										//转化为Buffer类型
val v: Array[T] = arr.array													//获取集合副本
val v: Array[T] = arr.clone()												//获取集合副本
val v: mutable.IndexedSeq[T] = arr.deep										//获取集合副本
val v: mutable.WrappedArray[T] = arr.repr									//获取集合副本			
val v: mutable.IndexedSeq[T] = arr.seq										//获取集合副本
val v: Map[K,V] = arr.toMap													//转化为Map
val v: Set[T] = arr.toSet													//去重复
val v: Iterator[T] = arr.toIterator											//一次迭代
val v: Stream[T] = arr.toStream												//不定数量元素遍历(懒加载)
val v: Array[T] = arr.padTo(len:Int, elem:T)								//新生成一个长度为len的数组,空余位置默认值为elem
val v: (Array[T], Array[T]) = arr.span(p:Int=>Boolean)						//从左到右至第一个不满足条件p的元素结束作为一个数组,剩余元素作为另一个数组,两个数组包装成元祖返回
val v: (Array[T], Array[T]) = arr.splitAt(index:Int)						//根据给定的index位置,分为两个数组,包装成元祖返回
val v: Array[Array[T]] = arr.transpose										//矩阵转置
val v: Array[(T, T)] = arr1.zip(arr2)										//将两个集合相同位置的下的两个元素组合成Tuple2,并返回成元祖,多余的长度会被忽略
val v: Array[(T, T)] = arr1.zipAll(arr2,this,that)							//将两个集合相同位置的下的两个元素组合成Tuple2,并返回成元祖,不足自动填充,this填充元祖_1的值,that填充元祖_2的值
val v: (Array[T], Array[T]) = arr.unzip										//将含有两个元素的数组,第一个元素取出组成一个序列,第二个元素组成一个序列
val v: (Array[T], Array[T], Array[T]) = arr.unzip3							//将含有三个元素的数组,对应位置的元素单独抽离分别包装成三个数组,并将三个数组包装成元祖返回
val v: Array[(T, T)] = arr.zipWithIndex										//序列中的每个元素和它的索引组成一个序列

详解:

array,clone(),deep,repr,seq的区别

//array是原数组的引用
val arr2: Array[Int] = arr1.array
println(arr2 == arr1)
println(arr2.equals(arr1))
println(arr2 != arr1)
println(arr2 ne arr1)
//结果:
true
true

//clone()新生成了一个数组
val arr3: Array[Int] = arr1.clone()
println(arr3 == arr1)
println(arr3.equals(arr1))
//结果:
false
false

//deep同clone()
val arr4: IndexedSeq[Any] = arr1.deep
println(arr4 == arr1)
println(arr4.equals(arr1))
//结果:
false
false

//repr同array
val arr5 = arr1.repr
println(arr5 == arr1)
println(arr5.equals(arr1))
//结果:
true
true

//seq
val arr6: mutable.IndexedSeq[Int] = arr1.seq
println(arr6 == arr1)
println(arr6.equals(arr1))
//结果:
false
false

toMap

转换成map类型

var rng = Array(("xiaohu", 23), ("mlxg",  11), ("midhu",  19), ("uzi",  23), ("ming", 22))

val map = rng.toMap
map.keySet.foreach(println)
map.values.foreach(println)

//结果
midhu
xiaohu
mlxg
uzi
ming
19
23
11
23
22

padTo

填充补齐序列

//如果当前序列长度小于 len,那么新产生的序列长度是 len,多出的几个位值填充 elem,如果当前序列大于等于 len ,则返回当前序列
-def padTo(len: Int, elem: A): Array[A] 

val a = Array(1, 2, 3, 4, 5)
val b = a.padTo(7,9)    	//需要一个长度为 7  的新序列,空出的填充 9
println(b.mkString(","))    //1,2,3,4,5,9,9

span/splitAt

分割一个序列为两个

//分割序列为两个集合,从第一个元素开始,直到找到第一个不满足条件的元素止,之前的元素放到第一个集合,其它的放到第二个集合
-def span(p: (T)Boolean): (Array[T], Array[T]) 

val a = Array(3,2,1,4,5)
val b = a.span( {x:Int => x > 2})
println(b._1.mkString(","))     //  3
println(b._2.mkString(","))     //  2,1,4,5

//从指定位置开始,把序列拆分成两个集合
-def splitAt(n: Int): (Array[T], Array[T]) 
val a = Array(3,2,1,4,5)
val b = a.splitAt(2)
println(b._1.mkString(",")) //  3,2
println(b._2.mkString(",")) //  1,4,5

transpose

二维矩阵转置

val chars = Array(Array("a","b"),Array("c","d"),Array("e","f"))
val v: Array[Array[String]] = chars.transpose
v.foreach(x=>{
    x.foreach(print)
    println()  
})

//
ace
bdf

zip/zipAll/unzip/zipWithIndex

数组组合

//将两个序列对应位置上的元素组成一个pair序列
-def zip[B](that: GenIterable[B]): Array[(A, B)] 

val a = Array(1,2,3,4,5)
val b = Array(5,4,3,2,1)
val c = a.zip(b)
println(c.mkString(","))        //(1,5),(2,4),(3,3),(4,2),(5,1)


//同zip,但是允许两个序列长度不一样,不足的自动填充,如果当前序列端,空出的填充为 thisElem,如果 that 短,填充为 thatElem
-def zipAll[B](that: collection.Iterable[B], thisElem: A, thatElem: B): Array[(A, B)] 
val a = Array(1,2,3,4,5,6,7)
val b = Array(5,4,3,2,1)
val c = a.zipAll(b,9,8)         //(1,5),(2,4),(3,3),(4,2),(5,1),(6,8),(7,8)

val a = Array(1,2,3,4)
val b = Array(5,4,3,2,1)
val c = a.zipAll(b,9,8)         //(1,5),(2,4),(3,3),(4,2),(9,1)


//将含有两个元素的数组,第一个元素取出组成一个序列,第二个元素组成一个序列
-def unzip[T1, T2](implicit asPair: (T)(T1, T2), ct1: ClassTag[T1], ct2: ClassTag[T2]): (Array[T1], Array[T2]) 

val chars = Array(("a","b"),("c","d"))
val b = chars.unzip
println(b._1.mkString(","))     //a,c
println(b._2.mkString(","))     //b,d


//序列中的每个元素和它的索引组成一个序列
-def zipWithIndex: Array[(A, Int)] 

val a = Array(10,20,30,40)
val b = a.zipWithIndex
println(b.mkString(","))        //(10,0),(20,1),(30,2),(40,3)

排序

val v: Array[T] = arr.reverse								//逆序
val v: Iterator[T] = arr.reverseIterator					//逆序迭代器
val v: Array[T] = arr.sorted								//升序
val v: Array[T] = arrReverse.sortBy(f:T=>B)					//x=>x 升序 | x=>-x 降序
val v: Array[T] = arr.sortWith(f:(T,T)=>Boolean)			//_<_ 升序 | _>_ 降序

字符串拼接

All:

addString

拼接字符串

val builder = new StringBuilder
//将数组中的元素逐个添加到builder
val str = arr1.addString(builder)
//每个元素用sep分隔符分开
val str1 = arr1.addString(builder, ",")
//在首尾各加一个字符串,并指定sep分隔符
val str2 = arr1.addString(builder, "{", ",", "}")

mkString

单集合拼接

//将数组中的元素逐个添加
println(arr1.mkString)
//每个元素用sep分隔符分开
println(arr1.mkString(","))
//在首尾各加一个字符串,并指定sep分隔符
println(arr1.mkString("{", ",", "}"))

//结果:
2456
2,4,5,6
{2,4,5,6}

根据值获取下标

val v: Int = arr.indexOf(v:T[,start:Int])							//从左向右,获取[从start位置开始]第一个为v的值的下标
val v: Int = arr.indexOfSlice(sub:GenSeq[,start:Int])				//从左向右,获取集合中第一个连续等于sub子序列值的首元素下标
val v: Int = arr.indexWhere(p:T=>Boolean[,start:Int])				//从左向右,获取集合中第一个符合参数函数条件p的下标
val v: Int = arr.lastIndexOf(v:T[,start:Int])						//从右向左,获取[从start位置开始]第一个为v的值的下标
val v: Int = arr.lastIndexOfSlice(sub:GenSeq[,start:Int])			//从右向左,获取集合中第一个连续等于sub子序列值的首元素下标
val v: Int = arr.lastIndexOfWhere(p:T=>Boolean[,start:Int])			//从右向左,获取集合中第一个符合参数函数条件p的下标
val v: Range = arr.indices											//返回当前序列索引集合
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值