我有一个字符串val trackingHeader = "k1=v1, k2=v2, k3=v3, k4=v4"
,我想解析它并将其转换为Map(k1 -> v1, k2 -> v2, k3 -> v3, k4 -> v4)
。以下是我用来执行此操作的代码:
val trackingHeadersMap = trackingHeader
.replaceAll("\\s", "")
.split(",")
.map(_ split "=")
.map { case Array(k, v) => (k, v) }
.toMap
我能够得到我想要的输出。但是,我还需要处理像val trackingHeader = "k1=v1, k2=v2, k3=v3, k4="
这样格式错误的输入案例。请注意,密钥k4
没有值。我的上述代码将开始使用scala.MatchError: [Ljava.lang.String;@622a1e0c (of class [Ljava.lang.String;)
,因此我将其更改为:
val trackingHeadersMap = trackingHeader
.replaceAll("\\s", "")
.split(",")
.map(_ split "=")
.collect { case Array(k, v) => (k, v) }
.toMap
很好,我现在也使用collect
来处理格式不正确的案例,但我想知道这个问题是什么密钥并将其记录下来(在此示例中为k4
)。我尝试了下面的内容,并且能够得到理想的结果,但我不确定它是否是正确的方法:
val badKeys = trackingHeader
.replaceAll("\\s", "")
.split(",")
.map(_ split "=")
.filterNot(_.length == 2)
现在我可以遍历badKeys
并打印出来。有更好的方法吗?
答案 0 :(得分:2)
您可以将结果设为可选,并使用flatMap
代替map
.flatMap {
case Array(k, v) => Some(k -> v)
case Array(k) => println(s"Bad entry: $k"); None
}
答案 1 :(得分:0)
一种解决方案是添加map
步骤,在调用collect
之前打印与单元素数组匹配的元素的错误键:
val trackingHeadersMap = trackingHeader
.replaceAll("\\s", "")
.split(",")
.map(_ split "=")
.map {
case v @ Array(k) => println(s"bad key: $k"); v
case v => v
}.collect {
case Array(k, v) => (k, v)
}
.toMap
更好的解决方案(将副作用与转换分开)将是使用partition
将其分成两个集合(“好”和“坏”),并分别处理每个集合:
val (good, bad) = trackingHeader
.replaceAll("\\s", "")
.split(",")
.map(_ split "=")
.partition(_.length == 2)
val trackingHeadersMap = good.map { case Array(k, v) => (k, v) }.toMap
bad.map(_(0)).foreach(k => println(s"bad key: $k"))