在Scala中,给定列表列表,如何从元素创建一个嵌套的HashMap?

时间:2016-05-05 01:36:24

标签: scala hashmap

在Scala中,给定列表列表,如何从元素创建一个嵌套的HashMap?我想将HashMap创建为分层树,以便对于索引i处的元素,索引i - 1处的元素是其父元素。

已知长度列表的示例:

val lst = List (
  List(34, 56, 78),
  List(34, 56,79),
  List (87, 23, 12),
  List(87, 90, 78),
  List(1, 45, 87)
)

scala> lst.groupBy(l => l(0))
  .mapValues(l => l.groupBy(x => x(1)))
  .mapValues{ case x => x.mapValues(y => y.map (z => z(2))) }
res2: scala.collection.immutable.Map[Int,scala.collection.immutable.Map[Int,List[Int]]] = Map(34 -> Map(56 -> List(78, 79)), 1 -> Map(45 -> List(87)), 87 -> Map(23 -> List(12), 90 -> List(78)))

当元素的长度已知但不适用于任意长度N时,此方法有效。是否有任何解决方案可以为每个列表具有相同长度的任何长度的列表创建此嵌套映射?

3 个答案:

答案 0 :(得分:3)

一些初步测试似乎表明这可能有效。

def nest(lli: List[List[Int]]): Traversable[_] =
  if (lli.head.size == 1)
    lli.flatten.distinct
  else
    lli.groupBy(_.head)
       .mapValues(vs => nest(vs.map(_.tail)))

答案 1 :(得分:0)

private def buildPartitionTree(partitionValues: List[List[Any]]): Map[Any, Any] = {
    val valuesAsNestedMaps = partitionValues.map(_.foldRight(Map[Any,Map[Any,_]]()) { case (partitionValue, map) =>
      Map(partitionValue.toString -> map)
    }).map(_.asInstanceOf[Map[Any, Any]])

    valuesAsNestedMaps.reduce[Map[Any, Any]] { case (map1: Map[Any, Any], map2: Map[Any, Any]) => mergeMaps(map1, map2) }
  }

private def mergeMaps(map1 : Map[Any, Any], map2 : Map[Any, Any]) = (map1.keySet ++ map2.keySet).map(key =>
    key -> mergeMapValues(map1.get(key), map2.get(key))
  ).toMap

private def mergeMapValues(o1 : Option[Any], o2 : Option[Any]): Any = (o1, o2) match {
    case (Some(v1: Map[Any, Any]), Some(v2: Map[Any, Any])) => mergeMaps(v1, v2)
    case (None, Some(x)) => x
    case (Some(y), None) => y
  }
val nestedMap = buildPartitionTree(lst)

答案 2 :(得分:0)

由于子列表的大小是任意的,因此您无法指定所需函数的结果类型。考虑引入这样的递归数据结构:

trait Tree[A]
case class Node[A](key:A, list:List[Tree[A]]) extends Tree[A]
case class Leaf[A](value:A) extends Tree[A]

现在您可以根据树创建产生所需结果的函数:

def toTree[A](key:A, list:List[List[A]]):Tree[A] = 
  if (list.exists(_.isEmpty)) Leaf(key)
  else Node(key, list.groupBy(_.head).map {case (k,v) => toTree(k, v.map(_.tail))}.toList)

由于你没有key的'root'值,你可以用一些假密钥调用toTree函数:

toTree(-1, lst)
res1: Node(-1,List(Node(34,List(Node(56,List(Leaf(79), Leaf(78))))), Node(1,List(Node(45,List(Leaf(87))))), Node(87,List(Node(23,List(Leaf(12))), Node(90,List(Leaf(78)))))))