数组这一章需要注意的要点是:
- 若长度固定则使用Array,若长度可能有变化则使用ArrayBuffer
- 提供初始值时不要使用new
- 用()来访问元素
- 用for(elem <- arr)来遍历元素
- 用for(elem <- arr if …) … yield … 来将原数组转型为新数组
- Scala数组和Java数组可以互操作;用ArrayBuffer,使用scala.collection.JavaConversions中的转换函数。
1. 编写一段代码,将a设置为一个n个随机整数的数组,要求随机数介于0(包含)和n(不包含)之间
2. 编写一个循环,将整数数组中相邻的元素置换。例如Array(1,2,3,4,5)经过置换后变为Array(2,1,4,3,5)
测试:
val a = Array(1,2,3,4,5)
Swap(a)
a.foreach(print)
输出结果为:
21435
3. 重复前一个练习,不过这一次生成一个新的值交换过的数组,用for/yield。
运行结果为:
4. 给定一个整数数组,产出一个新的数组,包含元素组中的所有正值,以原有顺序排列,之后的元素是所有零或负值,以原有顺序排序。
对于长度按需要变化的数组,Java中有ArrayList,C++中有vector。Scala中的等效数据结构为ArrayBuffer。可以用+=在尾端追加元素,比如b+=(1,2,3,4) , 可以用++=在尾端添加多个元素,以括号包起来,写成b++=Array(8,13,21)
运行结果为:
5. 如何计算Array[Double]的平均值
运行函数
6. 如何重新组织Array[Int]的元素将它们以反序排列? 对于ArrayBuffer[Int]你又会怎么做呢 ?
运行结果为:
对于ArrayBuffer,可以直接调用Reverse
7. 编写一段代码,产出数组中的所有值,去掉重复项。(提示:查看Scaladoc)
8. 重新编写3.4结尾的示例。收集负值元素的下标,反序,去掉最后一个下标,然后对每一个下标调用a.remove(i)。 比较这样做的效率和3.4节中另外两种方法的效率。
3.4节的示例是,给定一个整数的数组缓冲,我们想要移除除第一个负数之外的所有负数。传统的依次执行的解决方案会在遇到第一个负数时置一个标记,然后移除后续出现的负数元素。
var first = true
var n = a.length
var i = 0
while (i<n){
if (a(i)>=0) i+=1
else {
if (first) {first = false; i+=1}
else {a.remove(i); n-=1}
}
}
这个方案并不高效,因为从数组缓冲中移除元素并不高效,把非负数值拷贝到前端要好得多。首先收集需要保留的下标(注意只是下标,保存这些下标又占用了额外的空间,有别的方法么?):
var first = true
val indexes = for(i <- 0 until a.length if first || a(i)>=0) yield{
if(a(i)<0) first = false; i
}
然后将元素移动到该去的元素,并截断尾端:
for( j <- 0 until indexes.length) a(j) = a(indexes(j))
a.trimEnd(a.length - indexes.length)
这里的关键点是,拿到所有下标好过逐个处理。
可以写一个函数
然后执行
下面比较效率:
object Test{
def main(args: Array[String]){
var avgMilliSec = 0.0
val a = Array(-1,-2,3,0,1,2,5)
val n = 10000
var start = System.currentTimeMillis()
for (i <- 1 to n) {
val b = method1(a)
}
var end = System.currentTimeMillis()
var time = end - start
avgMilliSec = 1.0 * time / n
println("method 1 avg time: " + avgMilliSec)
start = System.currentTimeMillis();
for (i <- 1 to n) {
val b = method2(a)
}
end = System.currentTimeMillis()
time = end - start
avgMilliSec = 1.0 * time / n
println("method 2 avg time: " + avgMilliSec);
}
def method1(a:Array[Int])={
var first = true
val indexes = for(i <- 0 until a.length if first || a(i)>=0) yield {
if(a(i)<0) first = false; i
}
for (j <- 0 until indexes.length) a(j) = a(indexes(j))
val tmp = a.toBuffer
tmp.trimEnd(a.length - indexes.length)
tmp
}
def method2(arr:Array[Int])={
val ind = for(i <- 0 until arr.length if arr(i) < 0 ) yield i
val dropInd = ind.reverse.dropRight(1)
val tmp = arr.toBuffer
for(i <- dropInd) tmp.remove(i)
tmp
}
}
method 1 avg time: 0.0095
method 2 avg time: 0.0058
9.创建一个由java.util.TimeZone.getAvailableIDs返回的时区集合,判断条件是它们在美洲。去掉”America/”前缀并排序。
def TimeZone()={
val arr = java.util.TimeZone.getAvailableIDs()
val res = for(ele <- arr if ele.startsWith("America/")) yield {
ele.drop("America/".length)
}
scala.util.Sorting.quickSort(res)
res
}
10. 引入java.awt.datatransfer._ 并构建一个类型为SystemFlavorMap类型的对象:
val flavors = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf(SystemFlavorMap)
然后以DataFlavor.imageFlavor为参数调用getNativesForFlavor方法,以Scala缓冲保存返回值。(为什么用这样一个晦涩难懂的类?因为在Java标准中很难找得到使用java.util.List的代码。)
import java.awt.datatransfer._
val flavors = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]
println(flavors.getNativesForFlavor(DataFlavor.imageFlavor).toArray.toBuffer.mkString(" "))
答案是
这篇博客主要介绍了Scala中数组的操作,包括如何创建包含随机数的数组、交换相邻元素、使用for/yield生成新数组、筛选正负值、计算Double数组的平均值、反向排序数组、去除重复元素、高效移除负数、筛选美洲时区ID以及构建SystemFlavorMap对象。通过实例展示了Scala数组和ArrayBuffer的使用技巧。

648

被折叠的 条评论
为什么被折叠?



