Scala 以列表为键、字符串为值的地图展平

Posted

技术标签:

【中文标题】Scala 以列表为键、字符串为值的地图展平【英文标题】:Scala flatten a map with list as key and string as value 【发布时间】:2020-08-10 16:08:38 【问题描述】:

我有一个特殊的情况,我想像这样声明简单的配置

val config = List((("a", "b", "c"), ("first")), 
               (("d", "e"), ("second")),
               (("f"), ("third")))

在运行时,我想要一张地图,就像地图一样

"a" -> "first"
"b" -> "first"
"c" -> "first"
"d" -> "second"
"e" -> "second"
"f" -> "third"

使用toMap,我能够将config 转换为地图

scala> config.toMap
res42: scala.collection.immutable.Map[java.io.Serializable,String] = Map((a,b,c) -> first, (d,e) -> second, f -> third)

但我无法弄清楚如何将键列表扁平化为键,因此我得到了最终理想的形式。我该如何解决?

【问题讨论】:

这不是一个简单的配置,因为每个元组内部都有不同长度的元组(注意键类型是java.io.Serializable)。如果你在内部数据中使用Lists 而不是元组,它会容易得多。 你是对的。将键声明为列表而不是元组并结合下面发布的答案,我能够得到我想要的结果。谢谢! 【参考方案1】:

如果您使用List 构造您的config,则代码非常简单:

val config = List(
  (List("a", "b", "c"), ("first")),
  (List("d", "e"), ("second")),
  (List("f"), ("third")))

config.flatMap case (k, v) => k.map(_ -> v) .toMap

【讨论】:

【参考方案2】:

您可以尝试以下解决方案:

val config = List(
      (("a", "b", "c"), ("first")),
      (("d", "e"), ("second")),
      (("f"), ("third")))

val result = config.map 
  case (k,v) =>
    (
      k.toString().replace(")", "")
        .replace("(", "")
        .split(","), v)
  

val res = result.map 
  case (key,value) => key.map data =>
    (data,value)
  .toList
.flatten.toMap

如果您将配置结构更改为如下所示,解决方案会更简单:

val config1 = List (
  (List("a", "b", "c"), "first"),
  (List("d", "e"), "second"),
  (List("f"), "third")
)


config1.flatMap
  case (k,v) => k.mapdata => (data,v)
.toMap

【讨论】:

在你的第二个例子中,这里:case (k,v) => k.mapdata => (data,v).toMaptoMap 实际上并没有改变任何东西。您可以安全地删除它并节省一些 CPU 周期。【参考方案3】:

我认为以上答案是很好的实用答案。如果您处于无法控制输入的情况,并且您被Tuples 而不是Lists 卡住,我会这样做:

val result: Map[String, String] = config.flatMap  
  case (s: String, v) => List(s -> v)
  case (ks: Product, v) => ks.productIterator.collect  case s: String => s -> v 
  case _ => Nil //Prevent throwing
.toMap

这将丢弃键中不是String 的任何内容。

【讨论】:

【参考方案4】:

通过使用内置的 spark sql 函数

val config = List((Array("a", "b", "c"), ("first")),
      (Array("d", "e"), ("second")),
      (Array("f"), ("third"))).toDF(List("col1","col2") : _*)

config.withColumn("exploded",functions.explode_outer($"col1")).drop("col1").show()

【讨论】:

以上是关于Scala 以列表为键、字符串为值的地图展平的主要内容,如果未能解决你的问题,请参考以下文章

Scala如何展平嵌套的地图[字符串,任何]

字符串和成员函数指针的 C++ 映射

给定字符串替换子字符串,将字符串替换为键,替换为值。蟒蛇

如何初始化一个以结构为值的地图?

将其作为模型传递以在 grails 中查看时的映射问题

Scala:从地图中删除任何元素并展平