scala中的flatMap函数

scala中的flatMap函数,scala,flatmap,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; f

在下面两个场景中,我在列表中调用了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)

你能帮我解释一下为什么在第一种情况下,它的表现不符合预期吗

正如错误所述,您的类型是错误的

在第一种情况下,如果应用map而不是flatmap,则获得List[Array[Char]]。如果对其应用展平,将得到一个列表[Char]

在第二种情况下,如果应用map而不是flatmap,则获得List[Array[String]]。如果对其应用展平,则会得到一个列表[字符串]

我想您需要将数组中的字符串转换为字符,以使其正常工作


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

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

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)
您可以通过填写
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)
但我们正在通过

String => Array[Char]
编译器首先必须找到
Array[Char]
GenTraversableOnce[Char]
的适当隐式转换。也就是说,这应该是
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解释的类型推断原因,编译器无法选择
wrapcharray
conversion。正如所说的那样

Array
试图同时成为Java
Array
和Scala集合 时间它基本上成功了,但在某些极端情况下,两者都失败了

也许这是其中一个角落的情况。出于这些原因,最好避免使用
阵列
,除非性能或兼容性原因另有规定。然而,另一种在Scala2.13中似乎有效的方法是使用
to(Collection)
方法

List("abc","cde").flatMap(_.to(Array))

有趣
flatMap()
不会展平
列表[Array[Char]]
(场景1),但会展平
列表[Array[String]
(场景2)。在这两种情况下,如果您将
flatMap()
更改为
map()
,然后在最后添加
。flatte
,它们都可以工作。@jwvh是的,工作正常。在上面的上下文中我有点困惑。我认为区别在于场景1中实际上有一个
数组[B]
其中
B
Char
的一些尚未确定的超类型,它与搜索从
Array
GenTraversableOnce
的隐式转换相结合,会导致类型推断问题。顺便说一句,您可以直接拨打
列表(“abc”、“cde”)。展平
。感谢您的关注。但即使在我的第二个例子中,我提供给flatMap的函数文字也会生成一个数组。谢谢您的回复。我只是在Scala控制台中复制并粘贴您的代码片段。它给出了错误(方法flatMap的类型参数数目错误…)。我有Scala 2.12.8。这在更高版本的Scala中是固定的吗?我在我的计算机上运行你的代码,我有2.13。我用我得到的更新了我的答案。
List("abc", "cde").flatMap(e => wrapCharArray(augmentString(e).toArray))
List("abc","cde").flatMap(_.to(Array))