scala中的flatMap函数



在以下两个场景中,我在列表中调用了flatMap函数。在这两种情况下,flatMap函数的map部分都返回一个具有迭代器的数组。在第一种情况下,代码会出错,在第二种情况下会产生预期的结果。

场景-1

val x = List("abc","cde")
x flatMap ( e => e.toArray)
<console>:13: error: polymorphic expression cannot be instantiated to expected type;
found   : [B >: Char]Array[B]
required: scala.collection.GenTraversableOnce[?]
x flatMap ( e => e.toArray)

场景-2

val x = List("abc,def")
x flatMap ( e => e.split(",") )
res1: List[String] = List(abc, def) //Result

你能解释一下为什么在第一种情况下,它的行为没有达到预期吗?

我认为不同之处在于,在场景1中,实际上有一个Array[B],其中BChar的一些尚未确定的超类型。通常,编译器会寻找到GenTraversableOnce的隐式转换,但由于B还不为人所知,因此会遇到类型推断问题/限制。

您可以通过填写B来帮助进行类型推理。

List("abc", "cde").flatMap(_.toArray[Char])

或者更好的是,在这种情况下,您不需要flatMap。只需致电flatten即可。

List("abc", "cde").flatten

值得记住的是,Array不是一个合适的Scala集合,因此编译器必须更加努力地首先将其转换为适合Scala集合的其他集合

implicitly[Array[Char] <:< GenTraversableOnce[Char]] // error (Scala 2.12)
implicitly[Array[Char] <:< IterableOnce[Char]]       // error (Scala 2.13)

因此,因为flatMap取函数

String => GenTraversableOnce[Char]

但是我们正通过

String => Array[Char]

编译器首先必须找到CCD_ 11到CCD_。也就是说,这应该是wrapCharArray

scala.collection.immutable.List.apply[String]("abc", "cde").flatMap[Char](((e: String) => scala.Predef.wrapCharArray(scala.Predef.augmentString(e).toArray[Char]((ClassTag.Char: scala.reflect.ClassTag[Char])))))

或更短的

List("abc", "cde").flatMap(e => wrapCharArray(augmentString(e).toArray))

然而,由于Jasper-M解释的类型推断原因,编译器无法选择wrapCharArray转换。正如Daniel所说的

Array试图同时成为JavaArray和Scala Collection时间它基本上是成功的,但在某些情况下两者都失败了。

也许这就是其中一个角落案例。出于这些原因,除非性能或兼容性原因要求,否则最好避免使用Array。然而,在Scala2.13中似乎有效的另一种方法是使用to(Collection)方法

List("abc","cde").flatMap(_.to(Array))
scala> val x = List("abc","cde")
x: List[String] = List(abc, cde)
scala> x.flatMap[Char](_.toArray)
res0: List[Char] = List(a, b, c, c, d, e)

正如错误所提到的,您的类型是错误的。

在第一种情况下,如果appy-map不是flatmap,则获得List[Array[Char]]。如果你对此应用压平,你会得到一个List[Char]

在第二种情况下,如果appy-map不是flatmap,则获得List[Array[String]]。如果你对其应用扁平化,你会得到一个List[String]

我想您需要在数组中将String转换为Char,以便使其工作。

我使用Scala 2.13,但仍然有同样的错误。