在Scala中反转地图

时间:2018-06-27 16:12:39

标签: scala functional-programming for-comprehension

我正在Coursera中学习有关Scala函数式编程的课程。我在第六周。

我有以下代码:

/* define the map of numbers to letters */ 
val nmem = Map(
  '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", 
  '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ"
)

/* invert the map to get a map of letters to digits */
val charCode: Map[Char, Char] = 
  for {
       (digit, str) <- nmem
       ltr <- str
  } yield ltr -> digit

我的问题是理解力如何工作? nmem将键(字符)和值(字符串)引入digit和str。后来我们有了:ltr <-str,我不知道它是如何工作的,因为我不了解程序如何知道ltr是一个字符而不是一个字符串。

谢谢。

3 个答案:

答案 0 :(得分:2)

对这种for的理解被废止了

nmem.flatMap { case (digit, str) => str.map { ltr => (ltr, digit) } }

由于nmem的类型为Map[Char, String],因此编译器知道(digit, str)的类型必须为(Char, String)。因此,它知道str的类型为StringString的元素类型为Char,因此ltr的类型被推断为Char

如果您想写下类型推断的所有细节,您将得到如下信息:

nmem.flatMap[(Char, Char), Map[Char, Char]]{ 
  case (digit: Char, str: String) => 
  str.map[(Char, Char), Seq[(Char, Char)]]{ 
    (ltr: Char) => (ltr, digit) 
  } 
}

幸运的是,这不是必需的,因为可以自动推断所有这些类型。

答案 1 :(得分:0)

item <- collection语法通常用于遍历集合中的每个项目。

一个简单的例子是:

for(mapping <- map){
   println(mapping)
}

在您的情况下,这实际上是使用yield语法的嵌套for循环。

默认情况下,它将创建一个List并累积所有物品。

用更多的语法写可能会有所帮助:

val charCode : Map[Char,Char] = {  // Cast our result to a Map of (Char, Char)
    for ((digit, str) <- nmem;     // for every key-value pair (Char, String) in nmem
         ltr <- str)               // for every ltr (Char) in str (String)
    yield ltr -> digit             // add a new mapping to the map
}

您可以查看https://docs.scala-lang.org/../for-comprehensions.html以获得更多详细信息

答案 2 :(得分:-1)

第一个实际上 (digit, str) <- nmem ,从Map [String,String]中获取一个元组,下一个 ltr <- str 从中获取字符字符串。