Scala数组
⭐⭐⭐需要有一定Scala语法基础
数组要点
- 固定长度使用
Array
, 长度有可能变化使用ArrayBuffer
- 提供初始值不要使用
new
- 用
()
来访问数组
def main(args: Array[String]): Unit = {
//定长数组
val nums = new Array[Int](10)
//添加元素
nums(1) = 1
//提供初始值不用new
val nums2 = Array(1,2,3)
//使用()访问而不是[]
//修改数组
nums2(1) = 6;
println("修改后" + nums2(1))
/*ArrayBuffer 长度变化的数组,相当于java 的 arraylist*/
val ab = new ArrayBuffer[Int]
ab += 1 //在尾端添加元素 (1)
ab += (2,3,5,6,7) //尾端添加多个元素 (1, 2, 3, 5, 6, 7)
ab ++= Array(8,9,10) //追加任何集合 (1, 2, 3, 5, 6, 7, 8, 9, 10)
ab.trimStart(1);ab.trimEnd(3) //删除第一个元素和最后3个元素 (2, 3, 5, 6, 7)
ab.insert(2,4)//在索引2后面插入元素4,这样的操作并不是非常有效的,
//这需要扩大数组和平移元素 (2, 3, 4, 5, 6, 7)
ab.remove(2)//删除索引2所在的元素 (2, 3, 5, 6, 7)
ab.remove(2,3) //删除索引2及后面的2个元素(一共3个元素)(2, 3)
/*有时候你需要一个Array,但不知道最终装多少元素,这种情况下,
* 先构造一个ArrayBuffer
* 当确定好最终元素后调用:ab.toArray
* 反过来,ab.toBuffer来将数组ab转换成缓冲*/
}
- 用
for(elem <- arr)
来遍历元素 - 用
for(elem <- arr if ...) ... yield
来将原数组转为新数组
def main(args: Array[String]): Unit = {
//数组遍历
val nums3 = Array(1,2,3,4,5,6,7,8)
/*to方法生成的是一个包含起始值和结束值的闭区间
1 2 3 4 5 6 7 8 */
for(num <- 0 to nums3.length - 1) print(nums3(num))
/*until方法生成的是一个包含起始值
但不包含结束值的半开区间 1 2 3 4 5 6 7 8 */
for(num <- 0 until nums3.length ) print(nums3(num))
/*考虑步长的情况 1 3 5 7 */
for(num <- 0 until(nums3.length,2) ) print(nums3(num))
/*反转访问 8 7 6 5 4 3 2 1 */
for(num <- ( 0 until nums3.length ).reverse) print(nums3(num))
/*数组转换 这个操作会生成一个全新的数组 2 4 6 8 10 12 14 16*/
val nums4 = for(elem <- nums3) yield 2 * elem
//加入一些条件 4 8 12 16
val nums5 = for(elem <- nums3 if elem % 2 == 0) yield 2 * elem
/*另外的写法*/
val num6 = nums3.filter(_ %2 ==0 ).map(2 * _)
}
这些转换操作不会修改原数组,而是产生一个全新的数组。
从数组出发得到另一个数组, 从数组缓冲出发得到新的数组缓冲
一个示例:
给定一个整数的数组缓冲,我们想要移除除第一个负数之外的所有负数。传统的方法会在遇到第一个负数时置一个标记,然后移除后续出现的负数元素
def main(args: Array[String]): Unit = {
val ab = ArrayBuffer(-3, -2, -1, 0, 1, 2, 3, 4)
var first = true
var n = ab.length
var i = 0
while (i < n) {
if (ab(i) >= 0) {
i += 1
} else {
if (first) {
first = false
i += 1
} else {
ab.remove(i)
n -= 1
}
}
}
}
但实际上,写过算法题《移除元素》 的同学都知道,把非负数值拷贝到前端要好很多
val ab1 = ArrayBuffer(-3, -2, -1, 0, 1, 2, 3, 4)
var first = true;
//收集需要保留的下标
val indexes = for( i <- 0 until ab1.length if first || ab1(i) >= 0) yield{
if (ab1(i) < 0) first = false
i
}
//移动元素到该去的位置,并截断尾端
for( j <- 0 until indexes.length) ab1(j) = ab1(indexes(j) )
ab1.trimEnd(ab1.length - indexes.length)
println(ab1)
//这是一个数组!
val indexes = for( i <- 0 until ab1.length if first || ab1(i) >= 0) yield{
if (ab1(i) < 0) first = false
i
}
上面的另一种写法是:
for (i <- 0 until ab1.length) {
if (first || ab1(i) >= 0) {
indexes += i // 将满足条件的索引添加到索引数组中
if (ab1(i) < 0) {
first = false // 遇到第一个负数后,将 first 设置为 false
}
}
}
数组其他常用方法
val num = Array(1,2,3,4,5).sum //15 对ArrayBuffer同样有效
val bf1 = ArrayBuffer(1,2,5,7,0).max // 7 Array同样有效
val bf2 = ArrayBuffer(1,2,5,7,0).min // 0
val a = ArrayBuffer(1, 2, 5, 7, 0).sorted // (0, 1, 2, 5, 7)
val b = ArrayBuffer(1, 2, 5, 7, 0).sorted.reverse // (7, 5, 2, 1, 0)
//可以对一个数组直接调用排序,数组缓冲不行
val c = Array(1,4,3,8,9)
Sorting.quickSort(c) // 1 3 4 8 9
//mkString指定元素之间的分隔符
val str = Array("You", "I" ,"your friend steve")
println(str.mkString(" and "))
//结果: You and I and your friend steve
//还有一个重载是指定前中后缀
println(str.mkString("<", " and ", ">"))
//<You and I and your friend steve>
//count用于清点多少元素应该在用该函数后得到true
val d = Array(-1,2,-9,3,5,6)
println(d.count( _ < 0)) // 2 清点多少a的元素为正值
//append
val bbc = ArrayBuffer(1,2,3)
bbc.append(4,5)
println(bbc) // (1, 2, 3, 4, 5)
//appendAll将另一个集合中的所有元素
//添加到 ArrayBuffer 的末尾
val buffer = ArrayBuffer[Int]()
buffer.appendAll(Seq(1, 2, 3))
println(buffer) // 输出: ArrayBuffer(1, 2, 3)