2016-08-11 3 views
0

私はスカラを初めて使いました。関数がどのように組み合わされ、戻り値の型が混乱しているのか混乱しています。以下の点を考慮してくださいforeachとmapを使ったスカラ型の返り値

val nodes = List(0,1,2)    
val links = List(List(1, 2), List(1, 0), List(1,3)) 

タプル対「リンク」で説明したように、各ノードは、双方向リンクを有しています。私はそれの隣人に、各ノードポイントは、例えば

Map(0 -> List(1), 1 -> List(2, 0), 2 -> List(1)) 

しかし、これをコーディングする方法についての私の最初の考えは、私はそれが空の復帰だ理由について「リストを[任意]」の値を困惑しているマップを構築しようとしています。

nodes.foreach(z => (links.map { case List(a,b) => if(a == z) a else if (b == z) b })) 

これを行う正しい方法は何ですか。

+1

しないのはなぜ' 1:私が正しくあなたの質問を解釈する場合

そう、あなたはこのようなものが必要でしょうか? '3'は隣人じゃない?なぜそこに '3 - > List(1)'がないのですか? – jwvh

+0

ペアの表記は、 'val links = List(1 - > 2,1 - > 0)'や '(1,2)parens 'などです。 –

+0

@ som-snyttは言ったように、' Tuple2'そのペアには常に2つのアイテムが含まれていることがわかっているので、ペアの 'List'の代わりに。スカラーでは、Tuple2を作成するには 'Tuple2(a、b)'、 '(a、b)'、または 'a-> b'のいずれかを使用できます。 – Darkhan

答えて

3

あるいは、同様にコメントし

scala> nodes.map(n => (n, links.flatMap { 
    | case List(`n`, x) => Some(x) 
    | case List(x, `n`) => Some(x) 
    | case _ => None })) 
res3: List[(Int, List[Int])] = List((0,List(1)), (1,List(2, 0, 3)), (2,List(1))) 

scala> .toMap 
res4: scala.collection.immutable.Map[Int,List[Int]] = Map(0 -> List(1), 1 -> List(2, 0, 3), 2 -> List(1)) 
+0

更新しました。ユーザがマップを取得したいときに、最後に 'toMap'を呼び出すべきでしょう。 – Darkhan

+0

@ダルカンはい、私は他の答えにコメントするつもりでした。 –

0

あなたのコード内のいくつかの問題があります:すべての

まず、foreach戻りUnitあなたはまたScala Doc

に見ることができるよう、あなたの状態は完全に正しいではありませんが - 例えばノード0と接続1<->0の場合は、0を印刷しますが、実際には1を返します。 - これは、最後にtoMapを呼び出すための可能性を私に与え、私は(代わりにforeachの)nodesリストにmapを呼び出していますか

val nodes = List(0,1,2)    
val links = List(List(1, 2), List(1, 0), List(1,3)) 
val result = nodes.map(z => 
    (z, links.flatMap { 
       case List(a,b) => if(a == z && nodes.contains(b)) Some(b) else if (b == z && nodes.contains(a)) Some(a) else None 
       } 
    ) 
).toMap 
println(result) 

お知らせ:正しいコードは次のように行くだろう


- マップを返します(最終的に達成したいもの)。 (contains付き)私が発見した近隣ノードのコレクションの一部であるかどうかを確認する条件を追加しました:また、私はマップピングノードのPairに各ノードとその隣人の一覧

注2していますこれがあなたの例です。あなたが別の要件を持っている場合は、ちょうどそれが

与える削除:

Map(0 -> List(1), 1 -> List(2, 0), 2 -> List(1)) 
+0

結果に 'Unit'タイプが含まれているとは思いません。オプションを 'if'の中で使用し、最後に' flatten'を呼び出すことができます。 – Darkhan

+0

また、他の回答と同様に更新してください。 –

+0

非常に良い点、ありがとう、みんな。私は答えを – Anton

0

を私はどこを正確にわかりませんコード例でList[Any]を取得します。

ただし、foreachは、戻り値の型がUnitの関数を引数としてとり、Unitを返します。基本的に各ループの古典的なです。副作用についてはです。

Listコレクションの「マップ」機能がList[B]List[A]を変えることができます。したがって、たとえばmap関数のList[Int]またはIntのいずれかを返す場合は、のうち最も小さいものがの共通の祖先型のいずれもAnyになるので、結果はList[Any]になります。

しかし、scalaには非常に強力なコレクションAPIがあるため、簡単な解決策があります。

明示的に、あなたはCanBuildFrom[List[Int], List[Int], Map[Int, Int]]は(breakOutを見てください)Int => (Int, Int)

しかし Scalaはそれを達成するためにも、より簡単な方法を提供機能を使用してList[Int]しばらくマッピングからMap[Int, List[Int]]を構築するために提供することができます。 >一覧(0、2、3) ` -

val neighbors: Map[Int, List[Int]] = nodes.map(z => 
    z -> links.withFilter(_.contains(z)).flatMap(_.filter(candidate => candidate != z && nodes.contains(candidate))) 
)(collection.breakOut) 

--> neighbors: Map[Int,List[Int]] = Map(0 -> List(1), 1 -> List(2, 0), 2 -> List(1)) 
関連する問題