2017-03-24 15 views
0

ちょっと私は関数型プログラミングには全く新しいので、コードの平和を書くのに最もスケーラのような方法は何ですか?スカラコードprettification - ifステートメントを使用したループ2次元配列

var ANSWERS_ARRAY // Is array 
for ((rows, i) <- SOME_2D_ARRAY.view.zipWithIndex) 
     for ((col, j) <- rows.view.zipWithIndex) 
     if (col == SOME_VALUE) 
      // add tuple of (SOME_VALUE, (i,j)) to an ANSWERS_ARRAY 

ここで私は2D配列をループし、指定された要素が条件に一致するかどうかを確認しています。はいの場合は、新しい配列に配置します。それのための1つまたは2つのライナーはありますか?このコードは醜く非効率的なためです。

答えて

1

あなたのコードのロジックはそもそも非常に機能的ではありません。

関数プログラミングでは、通常、不変のデータを処理します。このデータでは、新しい不変の値を得るために関数を適用します。ここでは、answer_arrayの値を必然的に変更しようとしています。

それを行うための慣用的な方法は、以下のようになります。

val answerArray = my2DArray.zipWithIndex.flatMap { 
    case (row, i) => row.zipWithIndex.filter{ 
    case (col, j) => col == someValue 
    }.map { 
    case (col, j) => (someValue, (i, j)) 
    } 
} 

これは特に初心者のための非常に読みやすいコード、ないので、のは、それを分解してみましょう:

  • は最初、私たちは私たちを通過flatMapを使用して2D配列(インデックス付き)を作成します。これは各要素に作用する関数を取ります。この関数は、各要素に対して別の配列を返さなければならず、これらの配列をすべて1つに平坦化します(したがって、flatMapの "flat")。

  • 配列の要素は、初期配列の要素、つまり行とそのインデックスのペアであり、関数を正しく定義できるように、このペアでパターンを一致させます。

  • 今、各行について、私たちは何をしたいですか?条件を満たす要素のみを保持するようにしてください。つまり、filterという述語(これは、関数を返す関数の名前です)は、条件を満たす値のみを含む配列を返します。

  • ただし、これらの値は欲しいものではありませんが、それらを変換するので、mapを配列に適用します。 mapflatMapと同じですが、その引数だけが配列を返す必要はありません。戻り値は平坦化されないため(指定された関数によって最初の配列の要素の画像の配列が作成されるため)

  • 残りの要素にはどのような機能を適用しますか?さて、私たちはそう、私も(これは決して必要があるが)

は、[OK]をScalaであなたの変数に名前を付けるための慣用的な方法であるキャメルケースを使用し、トリプル(someValue, (i, j))

  • 予告をしたいです私たちが望むことをする素敵なコードがありますが、それはあまり読みにくくありません。ありがたいことに、flatMaps、maps、およびfiltersをより命令的なスタイルに置き換えるための、優れた構文砂糖のような言語です。これはコード作成の容易さのためだけであり、コンパイル時には、上記のコード(またはそれに近いもの)によってコードが置き換えられることに注意してください。

    val answerArray = for { 
        (row, i) <- 2DArray.zipWithIndex 
        (col, j) <- row.zipWithIndex 
        if col == someValue 
    } yield (someValue, (i, j)) 
    
    • <-ラインは

    • if行は我々が望む値に関する条件を表す(ボーナスとして、いくつかのパターンマッチングを用いて)、その要素にLHS名を割り当て、RHSアレイを横切ります維持する

    • yield部分は、最終アレイの各要素で取得する値です(各配列で抽出した値によって異なります)。

  • +0

    サー。このような簡単な答えをありがとう。 –

    +0

    申し訳ありません。私はむしろあなたが何をしているのか理解せずに関数型プログラミングのジャングルにあなたを残すよりも長い説明をしたいと思います。 –

    2

    簡単な解決策、zipWithIndexを使用してのために-理解:

    val SOME_2D_ARRAY: List[List[Int]] = ??? 
    val SOME_VALUE: Int = ??? 
    
    val ANSWERS_ARRAY: List[(Int, (Int, Int))] = for { 
        (rows, i) <- SOME_2D_ARRAY.zipWithIndex 
        (col, j) <- rows.zipWithIndex 
        if col == SOME_VALUE 
    } yield (SOME_VALUE, (i,j)) 
    

    あなたは(あなたのスニペットのように)怠惰な検索を実装する場合は、あなたはそれが好きで実装することができます。このバージョンでは、ANSWERS_ARRAYは遅延コレクションです。

    val ANSWERS_ARRAY = for { 
        (rows, i) <- SOME_2D_ARRAY.view.zipWithIndex 
        (col, j) <- rows.view.zipWithIndex 
        if col == SOME_VALUE 
    } yield (SOME_VALUE, (i,j))