2016-05-05 11 views
3

Scalaでは、リストのリストがあると、要素から1つの入れ子になったHashMapを作成するにはどうすればよいですか?私は、インデックスiの要素について、インデックスi-1の要素がその親であるような階層ツリーとしてHashMapを作成したいと思います。既知の長さのリストのScalaでは、リストのリストを渡して、どのようにして要素から1つの入れ子になったHashMapを作成できますか?

例:要素の長さが知られているが、任意の長さNのために動作しない場合

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

この方法が機能するために、このネストされたマップを作成することができます任意の解決策はありますすべてのリストの長さが同じ長さのリスト?

+0

なぜあなたはタグの1つとして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

これは動作しますが、具体的には、シリアル化要件のためにハッシュマップが必要です。 – bwin

関連する問題