快学Scala-第三章 数组相关操作

知识点:

1.定长数组 Array

val nums = new Array[Int](10) //10个整数的数组,所有元素初始化为0
val a = new Array[String](10) //10个元素的字符串数组,所有元素初始化为null
val s= Array("Hello","World") //长度为2的Array(String) 类型是编译器推断出来的,已提供初始值就不需要new
s(0) = "Goodbye" //Array("Google","World") 使用()而不是[]来访问元素

Scala的Array以Java数组方式实现,例子中的s对应的是java.lang.String[]

2.变长数组:数组缓冲 ArrayBuffer

对于长度按需要变化的数组,Java-ArrayList || C++-vector || Scala-ArrayBuffer

  val b = ArrayBuffer[Int]() //或者 new ArrayBuffer[Int]
  b += 1 //ArrayBuffer(1) 用 += 在尾端添加元素
  b += (1,2,3,4,5) //ArrayBuffer(1,1,2,3,4,5) 在尾端添加多个元素,用括号包起来
  b ++= Array(6,7,8) //ArrayBuffer(1,1,2,3,4,5,6,7,8) 用  ++= 追加任何集合
  b.trimEnd(5) //ArrayBuffer(1,1,2,3)移除最后5个元素

在数组缓冲的尾部添加或移除元素是一个高效的操作。也可以在任意位置插入和删除元素,这样的操作不高效,引发位置后的元素都必须被平移。

  b.insert(2, 9) //ArrayBuffer(1,1,9,2,3)
  b.insert(2, 10,11) //ArrayBuffer(1,1,10,11,9,2,3)
  b.remove(2) //ArrayBuffer(1,1,11,9,2,3)
  b.remove(2,3) //ArrayBuffer(1,1,3)

有时候你需要构建一个Array,但不知道元素有多少个,可以先构建ArrayBuffer,再调用b.toArray();反过来,调用a.toBuffer可以将一个数组a转换为一个数组缓冲。

3.遍历数组和数组缓冲

for(i <- 0 until a.length) //变量i值从0取到a.length-1
    println(i + ": " + a(i))

for(i <- 区间) 会让i遍历区间所有值。

0 until (a.length, 2)
  //Range(0,2,4,6,...) 每两个元素一跳

  (0 until a.length).reverse
  //Range(...,3,2,1,0) 逆序

  for(elem <- a)  //不使用数组下标时
    println(elem)

3.数组转换

val aa = Array(2,5,8,9)
  val result = for(elem <- aa) yield 2 * elem
  //result是Array(4,10,16,18)

for(…) yield 循环创建了一个类型与原始集合相同的新集合。结果包含yield之后的表达式,每次迭代对应一个。当你遍历一个集合时,你只想处理那些满足特定条件的元素,可以通过 守卫 :for 中的 if 实现。

for(elem <- aa if elem % 2 == 0) yield 2 * elem
//另一种实现方法
a.filter(_ % 2 == 0).map(2 * _)
a.filter{ _ % 2 == 0} map { 2 * _}

4.常用方法

sum\max\sorted sum方法的数组元素类型必须是数值类型,sorted方法将数组或缓冲数组排序后返回经过排序的数组或缓冲数组,不修改原始版本。

显示数组或缓冲数组的内容,可以用mkString方法。

5.多维数组是通过数组的数组实现的

  val matrix = Array.ofDim[Double](3,4)
  matrix(row)(column) = 42
//创建不规则的数组
  val triangle = new Array[Array[Int]](10)
  for(i <- 0 until triangle.length)
    triangle(i) = new Array[Int](i+1)


练习:(答案源链接

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

class test{
  def main(args:Array[Int]){
    getArr(10).foreach(println)
  }

  def getArr(n:Int): Array[Int] = {
    val a = new Array[Int](n)
    val rand = new scala.util.Random()
    for(i <- a) yield rand.nextInt()
  }

}

2.编写一个循环,将整数数组中相邻的元素置换

class test{
  def main(args:Array[Int]){
    val arr = Array(1,2,3,4,5)
    revert(arr)
    arr.foreach(println)
  }

  def revert(a:Array[Int]) = {
    for(i <- 0 until (a.length - 1,2)){
      val t = a(i)
      a(i) = a(i+1)
      a(i+1) = t
    }
  }
}

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

class test{
  def main(args:Array[Int]){
    val a = Array(1,2,3,4,5)
    val b = revertYield(a)
    b.foreach(println)
  }

  def revertYield(a:Array[Int]) = {
    for(i <- 0 until a.length) yield {
      if( i < (a.length - 1) && i % 2 == 0){
        //偶数下标时,则交换下一个相邻的元素值
        val t = a(i)
        a(i) = a(i+1)
        a(i+1) = t
      }
      a(i) //因为生成新的数组,每一个元素都要返回
    }
  }
}

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

import scala.collection.mutable.ArrayBuffer

class test{
  def main(args:Array[Int]){
    val a = Array(1,-2,0,4,5,0,-3)
    val b = reCombine(a)
    b.foreach(println)
  }

  def reCombine(a:Array[Int]) = {
    val buf = new ArrayBuffer[Int]();
    buf ++= (for( i <- a if(i > 0)) yield i)
    buf ++= (for( i <- a if(i == 0 || i < 0)) yield i)
    buf.toArray
  }
}

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

class test{
  def main(args:Array[Int]){
    val a = Array(1.0,5.6,0.0,-3.0)
    val b = average(a)
    println(b)
  }

  def average(a:Array[Double]) = {
    var t = 0.0
    for(i <- a){
      t += i
    }
    t/a.length
  }

  def ave(a:Array[Double]) = {
     a.sum / a.length
  }
}

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

import scala.collection.mutable.ArrayBuffer

object Hello {
  def main(args: Array[String]) {
  val a = Array(1,2,3,4,5)
    reverseArray(a)
    println("array reverse:")
    a.foreach(println)
    val b = a.reverse //将a的值逆序回去了
     b.foreach(println)

    println("bufferArray reverse:")
    val c = ArrayBuffer(6,7,8,9,0);
    val d = c.reverse
    d.foreach(println)
  }
  def reverseArray(a:Array[Int]) = {
    for( i <- 0 until (a.length / 2)){
      val t = a(i)
      a(i) = a(a.length-1-i)
      a(a.length-1-i)=t
    }
  }
}

7.编写一段代码,产出数组中的所有值,去掉重复项

import scala.collection.mutable.ArrayBuffer

object Hello {
  def main(args: Array[String]) {
    val ab = new ArrayBuffer[Int]()
    val c = new ArrayBuffer[Int]()
    println("Input the array line,separated by a space,ended with an enter.")
    val input = readLine().toString().split(‘ ‘);
    for(i <- input){
      ab += i.toInt
    }
//    ab.foreach(println)
    c ++= ab.distinct
    c.foreach(println)
  }
}

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

import scala.collection.mutable.ArrayBuffer

object Hello {
  def main(args: Array[String]) {
    val a = ArrayBuffer(1,2,4,-2,0,-1,-4,8)
    deleteNeg(a)
    a.foreach(println)
  }
  def deleteNeg(a:ArrayBuffer[Int]) = {
    val indexes = for(i <- 0 until a.length if a(i) < 0 ) yield  i
    //不能val b = indexex.reverse.trimEnd(1) reverse后,它是一个Seq序列。
    //value trimEnd is not a member of scala.collection.immutable.IndexedSeq[Int]
    val b = new ArrayBuffer[Int]()
    b ++= indexes.reverse
    b.trimEnd(1)
    //remove是ArrayBuffer的函数,如果传入的是Array,则需要调用toBuffer
    for(i <- b){
      a.remove(i)
    }
  }
}

9.创建一个由java.util.TimeZone.getAvailableIDs返回的时区集合,判断条件是它们在美洲,去掉”America/“前缀并排序。

import scala.collection.mutable.ArrayBuffer
import scala.collection.JavaConversions.asScalaBuffer

object Hello
{
  def main(args: Array[String])  = {
    var c = timeZoneName()
    c.foreach(println)
  }        

  def timeZoneName() = {
    val arr = java.util.TimeZone.getAvailableIDs();
    val tmp = (for (i <- arr if i.startsWith("America/")) yield {
      i.drop("America/".length)
    })
    scala.util.Sorting.quickSort(tmp)
    tmp
  }
}

10.引入java.awt.datatransfer._并构建一个类型为SystemFlavorMap类型的对象,然后以DataFlavor.imageFlavor为参数调用getNativesForFlavor方法,以Scala缓冲保存返回值。

import scala.collection.JavaConversions.asScalaBuffer
import scala.collection.mutable.Buffer
import java.awt.datatransfer._

object Hello
{
  def main(args: Array[String])  = {
     val flavors = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]
     val buf : Buffer[String] = flavors.getNativesForFlavor(DataFlavor.imageFlavor);
     buf.foreach(println);
  }
}
时间: 2024-10-06 20:25:13

快学Scala-第三章 数组相关操作的相关文章

快学Scala习题解答—第三章 数组相关操作

3 数组相关操作 3.1 编写一段代码,将a设置为一个n个随机整数的数组,要求随机数介于0(包含)和n(不包含)之间 random和yield的使用 Scala代码   import scala.math.random def randomArray(n:Int)={ for(i <- 0 until n) yield (random * n).toInt } println(randomArray(10).mkString(",")) 3.2 编写一个循环,将整数数组中相邻的元

从零学scala(二)数组相关操作、映射和元组

一:数组相关操作 定长数组 val array = Array[String]("a","b","c") //直接初始化数组的内容        println(array.mkString("|")) val array = new Array[String](2) //new一个长度为2的数据在通过更新的方法进行赋值        array.update(0, "0")        array.up

scala学习第三章数组相关操作

val b = new ArrayBuffer[Int]() //或者 new ArrayBuffer[Int] b += 1 //ArrayBuffer(1) 用+= 在尾端添加元素 b += (1,2,3,5) //ArrayBuffer(1,1,2,3,5) 在尾端添加多个元素 b ++= Array(1,2,3) //ArrayBuffer(1,1,2,3,5,1,2,3) 在尾端追加集合 用++= b.trimEnd(5) //ArrayBuffer(1,1,2) 移除最后5个元素 b

快学scala 第十一章 操作符 读书笔记及习题答案代码

chapter 11 操作符 标签:快学scala 一.笔记 scala种可以在反引号中包含几乎任何字符序列, val 'val' = 42 所有的操作符都是左结合的,除了以冒号(:)结尾的操作符,和赋值操作符.用于构造列表的::操作符是又结合的.1::2::Ni1的意思是1::(2::Ni1),先创建出包含2的列表,这个列表又被作为尾巴拼接到以1作为头部的列表中. 2. 函数调用语法:f(arg1, arg2,...)扩展到可以应用于函数之外的值,如果f不是函数或方法,那么这个表达式等于f.a

快学Scala 第三课 (定长数组,变长数组, 数组循环, 数组转换, 数组常用操作)

定长数组定义: val ar = new Array[Int](10) val arr = Array("aa", "bb") 定长数组赋值: arr(0) = "cc" 变长数组定义: val ab = new ArrayBuffer[String]() val ab1 = ArrayBuffer[String]() 定长数组增加元素: ab += "aa" ab += ("bb", "cc&q

快学Scala 第13章 集合 - 练习解答

1. 编写一个函数,给定字符串,产出一个包含所有字符的下标的映射.举例来说:indexes("Mississippi")应返回一个映射,让'M'对应集{0},'i'对应集{1,4,7,10},依此类推. 使用字符到可变集的映射.另外,你如何保证集是经过排序的? 回答:使用SortedSet可以保证集是经过排序的. package ex13_01 import scala.collection.mutable.SortedSet import scala.collection.mutab

快学Scala第14章----模式匹配和样例类

本章要点 match表达式是一个更好的switch,不会有意外掉入到下一个分支的问题. 如果没有模式能够匹配,会抛出MatchError.可以用case _ 模式来避免. 模式可以包含一个随意定义的条件,称作守卫. 你可以对表达式的类型进行匹配:优先选择模式匹配而不是isInstanceOf/asInstanceOf. 你可以匹配数组.元组和样例类的模式,然后将匹配到的不同部分绑定到变量. 在for表达式中,不能匹配的情况会被安静的跳过. 样例类继承层级中的公共超类应该是sealed的. 用Op

快学Scala第10章----特质

本章要点 类可以实现任意数量的特质 特质可以要求实现它们的类具备特定的字段.方法或超类 和Java接口不同,Scala特质可以提供方法和字段的实现 当你将多个特质叠加在一起时,顺序很重要--其方法先被执行的特质排在更后面 为什么没有多重继承 Scala和Java一样不允许类从多个超类继承:从多了超类继承可能会导致许多问题,例如两个超类有相同的方法,子类该如何使用和菱形继承.在java 中类只能扩展自一个超类,它可以实现任意数量的接口,但接口只能包含抽象方法,不能包含字段. Scala提供了特质(

快学Scala第13章----集合

本章要点 所有集合都扩展自Iterable特质 集合有三大类:序列.集.映射 对于几乎所有集合类,Scala都同时提供了可变的和不可变的版本 Scala列表要么是空的,要么拥有一头一尾,其中尾部本身又是一个列表 集是无先后次序的集合 用LinkedhashSet 来保留插入顺序,或者用SortedSet来按顺序进行迭代 '+' 将元素添加到无先后次序的集合中: +: 和 :+ 向前或向后追加到序列: ++将两个集合串接在一起: -和–移除元素 Iterable和Seq特质有数十个用于常见操作的方