如何将包含空数组的Array[Array[String]]展平为Array[String]?
解决Scala中包含空数组的二维数组展平问题
哈哈,这个问题我之前也踩过坑!让我帮你捋清楚哪里错了,以及怎么解决~
你的错误原因
你用flatMap(x => x.toString())的时候,犯了两个关键错误:
- 首先,
x是Array[String]类型,调用x.toString()会把整个数组转换成一个字符串(比如Array("foo")会变成"Array(foo)",空数组会变成"Array()"); - 其次,
flatMap的作用是把每个元素转换成一个可迭代对象,然后将所有元素“展平”到一个数组中。而字符串在Scala里属于字符序列(可迭代),所以flatMap会把x.toString()返回的字符串拆成一个个单独的字符,最终得到的就是一堆单个字符组成的数组——这就是你看到Array([f, o, o,..])的原因。
针对你需求的正确解法
根据你的示例,你希望把Array(Array("foo"), Array("bar"), Array())转换成Array("foo", "bar", ""),这里分两种场景给出解决方案:
场景1:每个子数组要么为空,要么只有一个元素(匹配你的示例)
如果你就是想把每个子数组映射成一个元素——非空子数组取它的唯一元素,空数组用空字符串""——直接用map即可,不需要flatMap:
val test = Array(Array("foo"), Array("bar"), Array()) val result = test.map(arr => arr.headOption.getOrElse("")) // 输出结果:Array[String] = Array(foo, bar, "")
这里headOption会返回子数组第一个元素的Option对象,数组为空时返回None;getOrElse("")则会在None的情况下返回空字符串,完美匹配你的需求。
场景2:子数组可能包含多个元素,同时保留空数组对应的空字符串
如果你的子数组可能有多个元素,想保留所有元素,同时把空数组转换成一个空字符串元素,那用flatMap配合条件判断:
val test = Array(Array("foo", "baz"), Array("bar"), Array()) val result = test.flatMap(arr => if (arr.isEmpty) Array("") else arr) // 输出结果:Array[String] = Array(foo, baz, bar, "")
这里flatMap会将每个子数组处理为:空数组变成包含""的数组,非空数组保留原数组,然后将所有元素展平到一个数组中,既保留了多元素子数组的所有内容,又处理了空数组的情况。
额外补充
如果只是想常规展平二维数组(空数组直接忽略,不生成任何元素),那直接用test.flatten或者test.flatMap(identity)就可以了,但这和你的期望结果不符,所以就不展开啦。
内容的提问来源于stack exchange,提问作者jOasis
相关产品推荐
相关产品推荐

