2011-07-05 81 views
4

我有一個返回Scala的映射值

[words: "one two", row: 23, col: 45] 

在階餘上述更改爲階地圖但然後我不得不將其聲明爲

Map[String, Any] 

一個函數(常規代碼)但其缺點是,如果我訪問的關鍵,如 地圖(「字」) 我要補充樣板

map2("words").asInstanceOf[String] 

scala中有更好的方法,不需要我添加asInstanceOf嗎?

回答

10

爲了避免靜電打字鑄造和好處,你可以返回一個元組(String, Int, Int)

def getResult = ("one two", 23, 45) 

val res = getResult 
res._1 // the line 

// alternatively use the extractor 
val (line, row, _) = getResult // col is discarded 
line // the line 
row // the row 

或使用的情況下,類結果:

case class MyResult(line: String, row: Int, col: Int) 

def getResult = MyResult("one two", 23, 45) 

val res = getResult 
res.line // the line 

// alternatively use the extractor provided by the case class 
val MyResult(line, row, _) = getResult // col is discarded 
line // the line 
row // the row 

我會更喜歡案例類,因爲這些字段是命名的,它實際上只是一行。

0

編輯:我已經瞭解到,您已經獲得了該地圖,並且需要一種更加乾淨的方式與其進行交互。當然,案例分析方法(如果適用)優於我在下面提出的方法。


如果你的鑰匙總是映射到相同的值類型,你可以做這樣的事情:

class TypedKey[T] { 
    def name = { 
    // assumes you declare only `object` instances 
    val simpleName = getClass.getSimpleName 
    val moduleName = if (simpleName.endsWith("$")) simpleName.substring(0, simpleName.size - 1) else simpleName 
    val lastDollar = moduleName.lastIndexOf('$') 
    if (lastDollar == -1) moduleName else moduleName.substring(lastDollar + 1) 
    } 
} 

object RubyKeys { 
    object words extends TypedKey[String] 
    object row extends TypedKey[Int] 
    object col extends TypedKey[Int] 
} 

class MapWrapper(val underlying: Map[String, Any]) { 
    def apply[T](key: TypedKey[T]) = underlying(key.name).asInstanceOf[T] 
} 

def main(args: Array[String]) { 

    val map = Map("words" -> "one two", "row" -> 23, "col" -> 45) 
    val wrapper = new MapWrapper(map) 

    import RubyKeys._ 

    val w = wrapper(words) // String 
    val r = wrapper(row) // Int 
    val c = wrapper(col) // Int 
    println(w, r, c) 
} 
0

只有兩個可能的值類型,在你的榜樣將允許使用Either類型與子類型LeftRight

val m = Map("words" -> Left("one two"), "rows"-> Right(23), "cols"-> Right(45)) 

如果從地圖上得到一個值,你可以查看你所擁有的,例如與模式匹配或使用isLeftisRight,並相應地「解開」它。

6

這是案例類是你的朋友。如果你的映射的鍵是大小寫類,那麼你可以強制客戶端代碼正確處理類型(並強制它正確處理所有類型)。

 S:\>scala 
    Welcome to Scala version 2.9.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_25). 
    Type in expressions to have them evaluated. 
    Type :help for more information. 

    scala> sealed abstract class Thing; 
    defined class Thing 

    scala> case class Toaster(slices: Int) extends Thing; 
    defined class Toaster 

    scala> case class Bucket(contents: String) extends Thing; 
    defined class Bucket 

    scala> val things = Map("toasty" -> Toaster(2), "buck" -> Bucket("stuff")); 
things: scala.collection.immutable.Map[java.lang.String,Product with Serializable with Thing] = Map(toasty -> Toaster(2), buck -> Bucket(stu 
ff)) 

scala> for (x <- things) x match { 
    case (k,Toaster(s)) => println(k + " " + s) 
    case (k,Bucket(c)) => println(k + " " + c) 
    } 
toasty 2 
buck stuff 

這裏的關鍵是匹配語句正在破解各種情況,併爲您提供正確類型的變量以匹配其中的字段。通過聲明抽象類是封閉的,你讓編譯器知道它有所有可用的子類。有了這些信息,它可以告訴你什麼時候你失蹤了,還可以做進一步的優化。