在以下两个场景中,我在列表中调用了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]
,其中B
是Char
的一些尚未确定的超类型。通常,编译器会寻找到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,但仍然有同样的错误。