如何将复杂的对象列表转换为 Scala 中的地图

How to convert complex list of objects into the map in Scala

我正在寻找将我的案例对象列表转换为地图的方法。这个

输入class看起来像这样

case class MyData(
    source: String,
    dataMap: Map[String, String]
)

结果classpost-转化

case class LiverampMappingV2(
    dataMapping: Map[String, Map[String, Seq[String]]]
)

例如输入数据如下 -->

val data = List(
      new myData("abc.com", Map("key1" -> "value1", "key2" -> "value2")),
      new myData("abc.com", Map("key1" -> "value11", "key3" -> "value3")),
      new myData("pqr.com", Map("key1" -> "value111", "key3" -> "value33"))
    )

将拼装如下

Map(
       key1 -> Map("abc.com" -> List("value1", "value11"), "pqr.com" -> List("value111")),
       key2 -> Map("abc.com" -> List("value2")),
       key3 -> Map("abc.com" -> List("value13"), "pqr.com" -> List("value33"))
   )

我尝试了几个选项,使用 groupBygroupMap 的组合,然后是 flatten 但是作为 scala 和函数式编程的新手,我无法找到最终的解决方案.

感谢任何帮助或指导。

如果范围内有 cats,这很简单,因为您可以利用 Map

Monoid
import cats.syntax.all._

def groupByNested(data: List[MyData]): Map[String, Map[String, List[String]]] =
  data.foldMap {
    case MyData(source, dataMap) =>
      dataMap.map {
        case (key, value) =>
          key -> Map(source -> (value :: Nil))
      }
  }

I am not totally happy with the function name.


可以看到运行here.

如果范围内没有猫,我也可以推荐另一种方法 :D 虽然这很冗长而且有点复杂。 那是因为您需要在每次迭代时折叠第一个原始“数据”。 但我会尽力解释:

type MP = Map[String, List[String]] 
// just for shortening the code, you can put a better name on it

data.foldLeft[Map[String, MP]](Map.empty)(
    (agg, newData) => {
      val source = newData.source
      newData.dataMap.foldLeft(agg) {
        case (updatingAggregator, (key, value)) =>
          updatingAggregator.updatedWith(key) {
            case Some(existingMap) =>
              Some(existingMap.updatedWith(source) {
                case Some(existingList) => Some(value :: existingList)
                case None => Some(value :: Nil)
              })
            case None =>
              Some(Map(source -> (value :: Nil)))
          }
      }
    }
  )

基本上我们在这里做的是折叠 data,零值为 empty Map of String to MP(这是我们希望从算法和折叠中得到的结果类型)。在每次迭代中,您都有源 (val source = ...)。您还有一个数据映射,您需要再次折叠它 (:D),并使用给定的源、键和值更新之前在其中创建的 agg 值。现在在 updatedWith 方法中,您基本上是在 updatingAggregator 中寻找 source,如果它已经有了,您只需在前面添加值,如果没有,您就添加它。 如果描述不够清楚,请告诉我。