【问题标题】:Scala flatten a map with list as key and string as valueScala 以列表为键、字符串为值的地图展平
【发布时间】: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 而不是元组,它会容易得多。
  • 你是对的。将键声明为列表而不是元组并结合下面发布的答案,我能够得到我想要的结果。谢谢!

标签: scala collections


【解决方案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.map{data => (data,v)}
    }.toMap
    

    【讨论】:

    • 在你的第二个例子中,这里:case (k,v) => k.map{data => (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()
      

      【讨论】:

        猜你喜欢
        • 2020-07-06
        • 2012-01-07
        • 1970-01-01
        • 2017-11-07
        • 2017-09-02
        • 1970-01-01
        • 1970-01-01
        • 2021-03-17
        • 2013-11-25
        相关资源
        最近更新 更多