Scala数组相关的操作

数组这一章需要注意的要点是:

  • 若长度固定则使用Array,若长度可能有变化则使用ArrayBuffer
  • 提供初始值时不要使用new
  • 用()来访问元素
  • 用for(elem <- arr)来遍历元素
  • 用for(elem <- arr if …) … yield … 来将原数组转型为新数组
  • Scala数组和Java数组可以互操作;用ArrayBuffer,使用scala.collection.JavaConversions中的转换函数。

1. 编写一段代码,将a设置为一个n个随机整数的数组,要求随机数介于0(包含)和n(不包含)之间

Scala数组相关的操作_第1张图片

2. 编写一个循环,将整数数组中相邻的元素置换。例如Array(1,2,3,4,5)经过置换后变为Array(2,1,4,3,5)

Scala数组相关的操作_第2张图片
测试:
val a = Array(1,2,3,4,5)
Swap(a)
a.foreach(print)
输出结果为:
21435

3. 重复前一个练习,不过这一次生成一个新的值交换过的数组,用for/yield。

Scala数组相关的操作_第3张图片
运行结果为:
Scala数组相关的操作_第4张图片

4. 给定一个整数数组,产出一个新的数组,包含元素组中的所有正值,以原有顺序排列,之后的元素是所有零或负值,以原有顺序排序。

对于长度按需要变化的数组,Java中有ArrayList,C++中有vector。Scala中的等效数据结构为ArrayBuffer。可以用+=在尾端追加元素,比如b+=(1,2,3,4) , 可以用++=在尾端添加多个元素,以括号包起来,写成b++=Array(8,13,21)
Scala数组相关的操作_第5张图片
运行结果为:
这里写图片描述

5. 如何计算Array[Double]的平均值

这里写图片描述
运行函数
Scala数组相关的操作_第6张图片

6. 如何重新组织Array[Int]的元素将它们以反序排列? 对于ArrayBuffer[Int]你又会怎么做呢 ?

Scala数组相关的操作_第7张图片
运行结果为:
这里写图片描述
对于ArrayBuffer,可以直接调用Reverse
Scala数组相关的操作_第8张图片

7. 编写一段代码,产出数组中的所有值,去掉重复项。(提示:查看Scaladoc)

这里写图片描述

8. 重新编写3.4结尾的示例。收集负值元素的下标,反序,去掉最后一个下标,然后对每一个下标调用a.remove(i)。 比较这样做的效率和3.4节中另外两种方法的效率。

3.4节的示例是,给定一个整数的数组缓冲,我们想要移除除第一个负数之外的所有负数。传统的依次执行的解决方案会在遇到第一个负数时置一个标记,然后移除后续出现的负数元素。

var first = true
var n = a.length
var i = 0
while (iif (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)

这里的关键点是,拿到所有下标好过逐个处理。
可以写一个函数
Scala数组相关的操作_第9张图片
然后执行
这里写图片描述
下面比较效率:

 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)