2016-05-05 62 views
3

在Scala中,給出一個列表清單,如何從元素中創建一個嵌套的HashMap?我想創建HashMap作爲分層樹,這樣對於索引爲i的元素,索引爲i - 1的元素是其父元素。在Scala中,給出一個列表清單,我如何從元素中創建一個嵌套的HashMap?

示例已知長度的列表:

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.不起作用是否有可以創建這個嵌套地圖的任何解決方案每個列表具有相同長度的任何長度的列表?

+0

爲什麼你把Java作爲你的一個標籤? –

+0

爲什麼你不會創建一個多樹數據結構? – Chris

回答

2

一些初步測試似乎表明這可能有效。

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))) 
+0

哇,這是美麗的,你可以想到的任何邊緣情況? – bwin

+0

如果不是所有的子列表都是相同的大小,你可能不會得到正確的結果,但到目前爲止,我還沒有看到它會拋出任何錯誤。 – jwvh

+0

我所有的子列表都是相同的大小。我在我的一些數據集和lgtm上進行了測試。再次感謝! – bwin

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) 
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) 

既然你沒有爲關鍵「根」的值,可以用一些假鑰匙撥打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))))))) 
+0

這個工作,但我特別需要一個hashmap爲我的序列化要求。 – bwin

相關問題