Scala - 数组
Scala 提供了一种数据结构 array,用于存储固定大小的相同类型的元素序列集合。数组用于存储一组数据,但通常将数组视为相同类型的变量集合更为有用。
与其声明单独的变量,如 number0、number1、... 和 number99,不如声明一个数组变量如 numbers,并使用 numbers[0]、numbers[1] 和 ... numbers[99] 来表示单独的变量。本教程介绍如何声明数组变量、创建数组以及使用索引变量处理数组。数组第一个元素的索引是 0,最后一个元素的索引是元素总数减一。
声明数组变量
要在程序中使用数组,必须声明一个变量来引用该数组,并指定该变量可以引用的数组类型。
以下是声明数组变量的语法。
语法
var z:Array[String] = new Array[String](3) or var z = new Array[String](3)
在这里,z 被声明为一个 String 数组,最多可容纳三个元素。可以为单个元素赋值或访问单个元素,使用如下命令即可实现 −
命令
z(0) = "Zara"; z(1) = "Nuha"; z(4/2) = "Ayan"
在这里,最后一个示例显示,索引通常可以是任何产生整数的表达式。还有一种定义数组的方式 −
var z = Array("Zara", "Nuha", "Ayan")
下图表示一个名为 myList 的数组。这里,myList 包含十个 double 值,索引从 0 到 9。
处理数组
处理数组元素时,我们经常使用循环控制结构,因为数组中的所有元素都是相同类型,并且数组的大小是已知的。
下面是一个示例程序,展示如何创建、初始化和处理数组 −
示例
object Demo {
def main(args: Array[String]) {
var myList = Array(1.9, 2.9, 3.4, 3.5)
// 打印所有数组元素
for ( x <- myList ) {
println( x )
}
// 对所有元素求和
var total = 0.0;
for ( i <- 0 to (myList.length - 1)) {
total += myList(i);
}
println("Total is " + total);
// 找出最大元素
var max = myList(0);
for ( i <- 1 to (myList.length - 1) ) {
if (myList(i) > max) max = myList(i);
}
println("Max is " + max);
}
}
将上述程序保存为 Demo.scala。以下命令用于编译和执行该程序。
命令
>scalac Demo.scala >scala Demo
输出
1.9 2.9 3.4 3.5 Total is 11.7 Max is 3.5
Scala 不直接支持各种数组操作,而是提供多种方法来处理任意维度的数组。如果要使用不同的方法,则需要导入 Array._ 包。
多维数组
在许多情况下,你需要定义和使用多维数组(即元素本身也是数组的数组)。例如,矩阵和表格就是可以用二维数组实现的数据结构。
以下是定义二维数组的示例 −
var myMatrix = ofDim[Int](3,3)
这是一个包含三个元素的数组,每个元素都是一个包含三个整数元素的整数数组。
尝试以下示例程序来处理多维数组 −
示例
import Array._
object Demo {
def main(args: Array[String]) {
var myMatrix = ofDim[Int](3,3)
// 构建一个矩阵
for (i <- 0 to 2) {
for ( j <- 0 to 2) {
myMatrix(i)(j) = j;
}
}
// 打印二维数组
for (i <- 0 to 2) {
for ( j <- 0 to 2) {
print(" " + myMatrix(i)(j));
}
println();
}
}
}
将上述程序保存为 Demo.scala。使用以下命令来编译和执行该程序。
命令
>scalac Demo.scala >scala Demo
输出
0 1 2 0 1 2 0 1 2
连接数组
尝试以下示例,它使用 concat() 方法来连接两个数组。你可以向 concat() 方法传递多个数组作为参数。
示例
import Array._
object Demo {
def main(args: Array[String]) {
var myList1 = Array(1.9, 2.9, 3.4, 3.5)
var myList2 = Array(8.9, 7.9, 0.4, 1.5)
var myList3 = concat( myList1, myList2)
// 打印所有数组元素
for ( x <- myList3 ) {
println( x )
}
}
}
将上述程序保存为 Demo.scala。使用以下命令来编译和执行该程序。
命令
>scalac Demo.scala >scala Demo
输出
1.9 2.9 3.4 3.5 8.9 7.9 0.4 1.5
使用范围创建数组
使用 range() 方法生成一个包含给定范围内递增整数序列的数组。你可以使用最后一个参数作为步长来创建序列;如果你不使用最后一个参数,则步长默认为 1。
让我们举一个创建范围 (10, 20, 2) 的数组示例:这意味着创建一个包含 10 到 20 之间元素且范围差为 2 的数组。数组中的元素是 10、12、14、16 和 18。
另一个示例:range (10, 20)。这里没有给出范围差,因此默认假设为 1 个元素。它会创建一个包含 10 到 20 之间元素且范围差为 1 的数组。数组中的元素是 10、11、12、13、... 和 19。
以下示例程序展示了如何使用范围创建数组。
示例
import Array._
object Demo {
def main(args: Array[String]) {
var myList1 = range(10, 20, 2)
var myList2 = range(10,20)
// 打印所有数组元素
for ( x <- myList1 ) {
print( " " + x )
}
println()
for ( x <- myList2 ) {
print( " " + x )
}
}
}
将上述程序保存为 Demo.scala。使用以下命令来编译和执行该程序。
命令
>scalac Demo.scala >scala Demo
输出
10 12 14 16 18 10 11 12 13 14 15 16 17 18 19
高级数组操作
Scala 中有各种高级数组操作。以下是一些示例:
- Mapping − 将 nums 数组中的每个元素平方并打印平方后的元素。
- Filtering − 从 nums 数组中过滤出偶数并打印。
- Zipping − 将 nums 数组与 letters 数组(Array('a', 'b', 'c', 'd'))进行拉链操作并打印拉链后的配对。
- Grouping − 根据 nums 数组中的元素是偶数还是奇数进行分组,然后打印分组后的元素。
示例
尝试以下示例,它在 Scala Arrays 中使用了上述方法 −
object Demo {
def main(args: Array[String]) = {
// 将元素映射为它们的平方
val nums = Array(1, 2, 3, 4)
val squares = nums.map(x => x * x)
println("Squared elements:")
squares.foreach(println)
// 过滤偶数
val evenNums = nums.filter(x => x % 2 == 0)
println("\nEven elements:")
evenNums.foreach(println)
// 拉链两个数组
val letters = Array('a', 'b', 'c', 'd')
val pairs = nums.zip(letters)
println("\nZipped elements:")
pairs.foreach { case (num, letter) => println(s"($num, $letter)") }
// 按偶数和奇数分组元素
val grouped = nums.groupBy(x => if (x % 2 == 0) "Even" else "Odd")
println("\nGrouped elements:")
grouped.foreach { case (key, value) => println(s"$key: ${value.mkString(", ")}") }
}
}
将上述程序保存为 Demo.scala。以下命令用于编译和执行此程序。
命令
\>scalac Demo.scala \>scala Demo
输出
Squared elements: 1 4 9 16 Even elements: 2 4 Zipped elements: (1, a) (2, b) (3, c) (4, d) Grouped elements: Odd: 1, 3 Even: 2, 4
Scala 数组方法
以下是在操作数组时可以使用的重要方法。如上所示,在使用任何上述方法之前,需要导入 Array._ 包。有关可用方法的完整列表,请查看 Scala 的官方文档。
| 序号 | 方法及描述 |
|---|---|
| 1 |
def apply( x: T, xs: T* ): Array[T] 创建 T 类型对象的数组,其中 T 可以是 Unit、Double、Float、Long、Int、Char、Short、Byte、Boolean。 |
| 2 |
def concat[T]( xss: Array[T]* ): Array[T] 将所有数组连接成单个数组。 |
| 3 |
def copy( src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int ): Unit 将一个数组复制到另一个数组。相当于 Java 的 System.arraycopy(src, srcPos, dest, destPos, length)。 |
| 4 |
def empty[T]: Array[T] 返回长度为 0 的数组。 |
| 5 |
def iterate[T]( start: T, len: Int )( f: (T) => T ): Array[T] 返回一个数组,该数组包含对起始值重复应用某个函数的结果。 |
| 6 |
def fill[T]( n: Int )(elem: => T): Array[T] 返回一个数组,该数组包含某个元素计算结果的多次重复。 |
| 7 |
def fill[T]( n1: Int, n2: Int )( elem: => T ): Array[Array[T]] 返回一个二维数组,该数组包含某个元素计算结果的多次重复。 |
| 8 |
def iterate[T]( start: T, len: Int)( f: (T) => T ): Array[T] 返回一个数组,该数组包含对起始值重复应用某个函数的结果。 |
| 9 |
def ofDim[T]( n1: Int ): Array[T] 创建具有指定维度的数组。 |
| 10 |
def ofDim[T]( n1: Int, n2: Int ): Array[Array[T]] 创建二维数组。 |
| 11 |
def ofDim[T]( n1: Int, n2: Int, n3: Int ): Array[Array[Array[T]]] 创建三维数组。 |
| 12 |
def range( start: Int, end: Int, step: Int ): Array[Int] 返回一个数组,该数组包含某个整数区间内等间隔的值。 |
| 13 |
def range( start: Int, end: Int ): Array[Int] 返回一个数组,该数组包含某个范围内递增整数序列。 |
| 14 |
def tabulate[T]( n: Int )(f: (Int)=> T): Array[T] 返回一个数组,该数组包含从 0 开始的整数值范围内给定函数的值。 |
| 15 |
def tabulate[T]( n1: Int, n2: Int )( f: (Int, Int ) => T): Array[Array[T]] 返回一个二维数组,该数组包含从 0 开始的整数值范围内给定函数的值。 |