在 Scala 中反转地图

Inverting a map in Scala

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

我有以下代码:

/* 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

我的问题是 for-comprehension 是如何工作的? nmem 将键(char)和值(string)引入到digit和str中。后来我们有: ltr <- str 我不知道它是如何工作的,因为我不明白程序如何知道 ltr 是一个字符而不是一个字符串。

提前谢谢你。

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

语法 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了解更多详情

这个for-理解被脱糖成

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

由于 nmem 的类型为 Map[Char, String],编译器知道 (digit, str) 的类型必须为 (Char, String)。因此,它知道 strString 类型。 String 的元素是 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) 
  } 
}

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