【问题标题】:如何按键 Scala 2.11.x 对地图列表进行分组
【发布时间】:2022-01-20 21:20:49
【问题描述】:

鉴于以下地图列表(列表可能更长):

List(
    Map[String,String]("wind"->"none", "rain"->"none", "class"->"on time"),
    Map[String,String]("wind"->"none", "rain"->"slight", "class"->"on time"),
    Map[String,String]("wind"->"none", "rain"->"slight", "class"->"late"),
    ...
)

我怎样才能对我有这样的地图进行分组:

"on time" -> ("wind"->"none", "rain"->"none", "wind"->"none", "rain"->"slight")
"late" -> ("wind"->"none", "rain"->"slight")

我在多张地图上工作时卡住了。

【问题讨论】:

    标签: scala group-by functional-programming maps


    【解决方案1】:

    另一种选择:

    val maps =
      List(
        Map[String, String]("wind" -> "none", "rain" -> "none", "class" -> "on time"),
        Map[String, String]("wind" -> "none", "rain" -> "slight", "class" -> "on time"),
        Map[String, String]("wind" -> "none", "rain" -> "slight", "class" -> "late"),
        Map[String, String]("wind" -> "none", "rain" -> "slight")
      )
    
    val grouped = maps.foldLeft(Map.empty[String, List[(String, String)]]) {
      case (acc, map) if map.contains("class") =>
        val key = map("class")
        if (acc.contains(key))
          acc.updated(key, acc(key) ++ (map - "class").toList)
        else 
          acc + (key -> (map - "class").toList)
      case (acc, _) => acc
    }
    

    【讨论】:

    【解决方案2】:

    在原版 Scala 2.12\2.11 中假设起点:

    val maps =
      List(
        Map[String, String]("wind" -> "none", "rain" -> "none", "class" -> "on time"),
        Map[String, String]("wind" -> "none", "rain" -> "slight", "class" -> "on time"),
        Map[String, String]("wind" -> "none", "rain" -> "slight", "class" -> "late")
      )
    

    你可以折叠所有东西:

    maps
      .filter(_.contains("class")) // guarantee "class" key exists
      .map(m => m("class") -> (m - "class").toList)
      .foldLeft(Map.empty[String, List[(String, String)]]) { 
        case (acc, (key, values)) if acc.contains(key) => 
          acc.updated(key, acc(key) ++ values)
        case (acc, (key, values)) => 
          acc + ((key, values))
      }
    

    这个逻辑对于任何输入都是安全的,因为它会在没有 class 键的情况下过滤掉 Map[_,_]。 您可以删除 .map(..) 并在 fold 中一次性完成所有操作。

    如果您可以保证输入不为空并且包含密钥 class,您可以使用 reduceLeft 而不是 foldLeft 并删除 filter

    奖励逻辑与Iterator[_]兼容:

    maps
      .iterator
      .filter(..)
      .map(..)
      .foldLeft(..)(..)
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-21
      • 2018-06-21
      • 2022-06-17
      • 1970-01-01
      • 1970-01-01
      • 2018-07-19
      • 2021-07-11
      • 1970-01-01
      • 2022-01-08
      相关资源
      最近更新 更多