在 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)
。因此,它知道 str
是 String
类型。 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)
}
}
幸运的是,这不是必需的,因为所有这些类型都可以自动推断出来。
我正在 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)
。因此,它知道 str
是 String
类型。 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)
}
}
幸运的是,这不是必需的,因为所有这些类型都可以自动推断出来。