0

我正在尝试掌握flatMapScala 中的实现。基于Scala编程中的定义

返回元素列表作为其正确参数的函数。它将函数应用于每个列表并返回所有函数结果的串联。

现在要理解这一点,我有以下实现

val listwords = List(List("abc"),List("def"),List("ghi"))

val res2 = listwords flatMap (_+"1")
println(res2) //output- List(L, i, s, t, (, a, b, c, ), 1, L, i, s, t, (, d, e, f, ), 1, L, i, s, t, (, g, h, i, ), 1)

val res3 = listwords flatMap (_.apply(0).toCharArray())
println(res3) //output- List(a, b, c, d, e, f, g, h, i)

看着让我发疯的第一个输出,为什么会List[List[String]]被这样对待List[String]

毕竟有了上述问题的答案,请有人帮我执行一个操作,该操作需要选择每个内部的第一个字符串的第一个字符并产生一个List[Char]. 因此,鉴于listwords,我希望输出为List('a', 'd', 'g')

4

4 回答 4

1

代码listwords flatMap (_+"1")可以重写为listwords flatMap (list => list.toString + "1"). 因此,您基本上使用 toString 方法将所有列表转换为字符串。

要获取第一个字符,您可以使用以下表达式:

listwords.flatMap(_.headOption).flatMap(_.headOption)
于 2016-05-17T09:50:57.930 回答
1

List("abc") + "1"等价于List("abc").toString + "1"所以它返回字符串“List(a, b, c)1”。的类型List.flatMap

flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): List[B]

并且您的函数具有 type (List[String] => String)String扩展GenTraversableOnce[Char],因此您的结果列表具有类型List[Char].

于 2016-05-17T09:50:33.323 回答
0

_+"1"没有做你认为它正在做的事情。

它被解释为list: List[String] => list.+("1")

由于List[String]不包含这样的方法,编译器会在范围内寻找隐式转换。它发现any2stringadd. (有关隐式转换的更多信息,请参阅http://docs.scala-lang.org/tutorials/tour/implicit-conversions )

implicit final class any2stringadd[A](private val self: A) extends AnyVal {
  def +(other: String): String = String.valueOf(self) + other
}

list: List[String] => list.+("1")

现在变成

list: List[String] => new any2stringadd(list).+("1")

返回String.valueOf(list) + "1"

于 2016-05-17T10:06:16.507 回答
0

首先,您需要了解mapflatMap方法之间的区别。它们都遍历某个容器并将函数文字应用于每个元素。不同之处在于,flatMap它又进行了一项额外的操作:它使容器的结构变平。还有一种方法可以让您只进行展平及其调用flatten(因此flatMap相当于map操作后跟flatten操作)。您必须记住的第二件事是您正在修改(映射)嵌套列表,因此您还需要嵌套map/flatMap调用。这些示例应该向您阐明所有这些事情:

scala> val wordLists = List(List("abc"),List("de"),List("f"), List())
wordLists: List[List[String]] = List(List(abc), List(de), List(f), List())

scala> val words = wordsLists.flatten
words: List[String] = List(abc, de, f)

scala> val replacedWordLists = wordsLists.map(_ => List("xyz"))
replacedWordLists: List[List[String]] = List(List(xyz), List(xyz), List(xyz), List(xyz))

scala> val replacedWords = wordsLists.map(_ => List("xyz")).flatten // Equivalent: wordsLists.flatMap(_ => List("xyz"))
replacedWords: List[String] = List(xyz, xyz, xyz, xyz)

scala> val upperCaseWordLists = wordsLists.map(_.map(_.toUpperCase))
upperCaseWordLists: List[List[String]] = List(List(ABC), List(DE), List(F), List())

scala> val upperCaseWords = wordsLists.map(_.map(_.toUpperCase)).flatten // Equivalent: wordsLists.flatMap(_.map(_.toUpperCase))
upperCaseWords: List[String] = List(ABC, DE, F)

scala> val optionalFirstLetterLists = wordLists.map(_.map(_.headOption))
optionalFirstLetterLists: List[List[Option[Char]]] = List(List(Some(a)), List(Some(d)), List(Some(f)), List())

scala> val optionalFirstLetters = wordLists.map(_.map(_.headOption)).flatten // Equivalent: wordLists.flatMap(_.map(_.headOption))
optionalFirstLetters: List[Option[Char]] = List(Some(a), Some(d), Some(f))

scala> val firstLetterLists = wordLists.map(_.map(_.headOption).flatten) // Equivalent: wordLists.map(_.flatMap(_.headOption))
firstLetterLists: List[List[Char]] = List(List(a), List(d), List(f), List())

scala> val firstLetters = wordLists.map(_.flatMap(_.headOption)).flatten // Equivalent: wordLists.flatMap(_.flatMap(_.headOption))
firstLetters: List[Char] = List(a, d, f)
于 2016-05-17T10:32:44.990 回答