映射和元组

Posted 我是一个粉刷匠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了映射和元组相关的知识,希望对你有一定的参考价值。

知识点:

1.构造映射,映射是对偶的集合

val scores1 = Map("Alice" -> 10, "Bob" -> 7, "Cindy" -> 9) //不可变映射
// val scores1 = Map(("Alice",),("Bob",),("Cindy",))
val scores2 = scala.collection.mutable.Map("Alice" -> 10, "Bob" -> 7, "Cindy" -> 9) //可变映射
//构造一个空的映射
val scores3 = new scala.collection.mutable.HashMap[String,Int]

2.获取映射中的值

val bobscore = scores1("Bob") //如果不包含,则抛出异常
val bobscore1 = if(scores1.contains("Bob")) scores1("Bob") else 0
val bobscore2 = scores1.getOrElse("Bob", 0)

3.更新映射、迭代映射

在可变映射中,可以更新某个映射的值,或者添加一个新的映射关系,做法是在=号的左侧使用()

//可变映射
scores2("Bob") = 9
scores2("Fred") = 8
scores2 += ("Bob" -> 9, "Fred" -> 8)
scores2 -= "Alice"
     
//不可变映射 
val newscores = scores1 + ("Bob" -> 9, "Fred" -> 8) //更新过的新映射,将结果作为新值保存
//更新var变量
var varscores =  Map("Alice" -> 10, "Bob" -> 7, "Cindy" -> 9)
varscores = varscores + ("Bob" -> 9, "Fred" -> 8)
varscores = varscores - "Alice"
     
//迭代映射
for((k,v) <- scores1) //处理k,v
scores1.keySet        //获得类似于 Set("a","b","c")这样的集合
for(v <- scores1.values) println(v) //values方法返回一个Iterable,可以在for循环中使用
for((k,v) <- scores1) yield (v,k) //反转一个映射

4.已排序映射

如下得到不可变的树型映射:

val scores4 = scala.collection.immutable.SortedMap("Alice" -> 10, "Bob" -> 7, "Cindy" -> 9)

对于可变的树型映射,最接近的选择是使用Java的TreeMap。

如果按插入顺序访问所有键,则使用LinkedHashMap。

val months = scala.collection.mutable.LinkedHashMap("January" -> 1,"February" -> 2,"March" -> 3,"April" -> 4, "May" -> 5,...)

5.与Java的互操作

将Java映射转换成一个Scala映射,以便使用更便捷的Scala映射API,这对于需要操作Scala并未提供的可变树形映射很有用。

import scala.collection.JavaConversions.mapAsScalaMap
//指定Scala映射类型
val scores : scala.collection.mutable.Map[String,Int] = new java.util.TreeMap[String,Int]
     
//java.util.Properties->Map[String,String]
import scala.collection.JavaConversions.propertiesAsScalaMap
val props : scala.collection.Map[String,String] = System.getProperties()
     
//scala映射传递给预期的Java映射方法
import scala.collection.JavaConversions.mapAsJavaMap
import java.awt.font.TextAttribute._ //引入下面的映射会用到的键
val attrs = Map(FAMILY -> "Serif", SIZE -> 12) //scala映射
val font = new java.awt.Font(attrs) //该方法预期一个Java映射

6.元组

映射是键/值对偶的集合,对偶是元组的最简单形态——元组是不同类型的值的聚集

元组的值是通过将单个的值包含在圆括号中构成的。使用_1 、_2 、_3访问其组元,元组的各组元从1开始。

val = (1,3.14,”Fred”)

val second = t._2 //second设为3.14

亦可 val second = t _2

7.拉链操作

val symbols = Array("<","-",">")
val counts = Array(2,10,2)
val pairs = symbols.zip(counts)
pairs.toMap   //拉链操作组合成一个映射

练习:(参考答案原网址

1.设置一个映射,其中包含你想要的一些装备,以及它们的价格。然后构建另一个映射,采用同一组键,但是价格上打9折

scala> val price = Map("ipad" -> 4000,"iPhone" -> 6000, "iWatch" -> 3000)
price: scala.collection.immutable.Map[String,Int] = Map(ipad -> 4000, iPhone ->
6000, iWatch -> 3000)

scala> val newprice = for((k,v) <- price) yield (k, v * 0.9)
newprice: scala.collection.immutable.Map[String,Double] = Map(ipad -> 3600.0, iP
hone -> 5400.0, iWatch -> 2700.0)

2.编写一段程序,从文件中读取单词。用一个可变映射来清点每个单词出现的频率。读取这些单词的操作可以使用java.util.Scanner: 
val in = new java.util.Scanner(new java.io.File("myfile.txt")) while(in.hasNext()) 处理 in.next() 或者翻到第9章看看更Scala的做法。 最后,打印出所有单词和它们出现的次数。

import scala.io.Source
import scala.collection.mutable.HashMap

object Pract {
   def main(args: Array[String])  = {
      val source = Source.fromFile("file.txt").mkString
      val tokens = source.split("\\s+")
      val map = new HashMap[String,Int]
      
      for(key <- tokens){
        map(key) = map.getOrElse(key, 0) + 1
      }
      println(map.mkString(","))      
   }
}

3.重复前一个练习,这次用不可变的映射

不可变映射与可变映射的区别就是每次添加新的元素时都会返回一个新的映射。

import scala.io.Source

object Pract {
   def main(args: Array[String])  = {
      val source = Source.fromFile("file.txt").mkString
      val tokens = source.split("\\s+")
      var map = Map[String,Int]() //注意这里用的 var 了
      
      for(key <- tokens){
          map += (key -> (map.getOrElse(key, 0) + 1))
      }
      println(map.mkString(","))      
   }
}

4.重复前一个练习,这次使用已排序的映射,以便单词可以按顺序打印出来

import scala.io.Source
import scala.collection.SortedMap

object Pract {
   def main(args: Array[String])  = {
      val source = Source.fromFile("file.txt").mkString
      val tokens = source.split("\\s+")
      var sortedmap = SortedMap[String,Int]() //注意这里用的 var 了
      
      for(key <- tokens){
          sortedmap += (key -> (sortedmap.getOrElse(key, 0) + 1))
      }
      println(sortedmap.mkString(","))      
   }
}

5.重复前一个练习,这次使用java.util.TreeMap并使之适用于Scala API

import scala.io.Source
import scala.collection.mutable.Map
import scala.collection.JavaConversions.mapAsScalaMap
import java.util.TreeMap

object Pract {
   def main(args: Array[String])  = {
      val source = Source.fromFile("file.txt").mkString
      val tokens = source.split("\\s+")
      val map:Map[String,Int] = new TreeMap[String,Int]
      
      for(key <- tokens){
         map(key) = map.getOrElse(key, 0) + 1
      }
      println(map.mkString(","))   
   }
}

6.定义一个链式哈希映射,将"Monday"映射到java.util.Calendar.MONDAY,依次类推加入其他日期。展示元素是以插入的顺序被访问的

import scala.collection.mutable.LinkedHashMap
import java.util.Calendar

object Pract {
   def main(args: Array[String])  = {
      val map = new LinkedHashMap[String, Int]
      map += ("MONDAY" -> Calendar.MONDAY)
      map += ("TUESDAY" -> Calendar.TUESDAY)
      map += ("WENDSDAY" -> Calendar.WEDNESDAY)
      map += ("THURSDAY" -> Calendar.THURSDAY)
      map += ("FRIDAY" -> Calendar.FRIDAY)
      map += ("SATURDAY" -> Calendar.SATURDAY)
      map += ("SUNDAY" -> Calendar.SUNDAY)
      println(map.mkString(","))   
   }
}

7.打印出所有Java系统属性的表格

JAVA系统属性转scala map的使用

import scala.collection.JavaConversions.propertiesAsScalaMap
import scala.collection.Map

object Pract {
   def main(args: Array[String])  = {
      val props: Map[String,String] = System.getProperties
      val keys = props.keySet
      val keylength = for( key <- keys) yield key.length
      val maxlength = keylength.max
      for( key <- keys) {
        print(key)
        print(" " * (maxlength - key.length))
        print("| ")
        println(props(key))
      }

   }
}

8.编写一个函数minmax(values:Array[Int]),返回数组中最小值和最大值的对偶

def minmax(values:Array[Int])  = {
     (values.max,values.min)
   }

9.编写一个函数Iteqgt(values:Array[int],v:Int),返回数组中小于v,等于v和大于v的数量,要求三个值一起返回

def Iteqgt(values:Array[Int],v:Int) = {
     var a,b,c=0
     for(value <- values){
       if(value > v) a += 1
       else if(value == v) b += 1
       else c += 1
     }
     (a,b,c)
   }
   
   def Iteqgt1(values:Array[Int],v:Int) = {
     (values.count(_ > v),values.count(_ == v), values.count(_ < v))
   }

10.当你将两个字符串拉链在一起,比如"Hello".zip("World"),会是什么结果?想出一个讲得通的用例

scala> "Hello".zip("world")
res0: scala.collection.immutable.IndexedSeq[(Char, Char)] = Vector((H,w), (e,o),
 (l,r), (l,l), (o,d))

以上是关于映射和元组的主要内容,如果未能解决你的问题,请参考以下文章

映射和元组

映射和元组

Scala的映射和元组操作

「大数据」(八十九)Scala之映射和元组

从零学scala数组相关操作映射和元组

无法使用 Pig 中的 Elephant Bird 访问带有包和元组的嵌套 JSON