4

ここでパターン マッチングのハンドルを取得しようとしています。C++/Java のバックグラウンドを持っているため、私には非常になじみがありません。

この分岐のポイントはd、タプルのリスト [(string,object) の形式) の各メンバーをチェックすることです。3 つのケースを定義したいと思います。

1) この関数のカウンターがリストのサイズ (acc と呼ばれる別の関数で定義) よりも大きい場合、何も返しません (一致がないため) 2)key入力で指定された値がリストのタプルと一致する場合、その値(または、タプルに格納されているものは何でも._2)を返したいです。3) 一致がなく、反復するリストがまだある場合は、インクリメントして続行します。

私のコードは以下の通りです:

def get(key:String):Option[Any] = {

        var counter: Int = 0
        val flag: Boolean = false 

        x match {

                case (counter > acc) => None

                case ((d(counter)._1) == key) => d(counter)._2

                case _ =>   counter += 1
                }

ここでの私の問題は、最初のケースは正しくコンパイルされているように見えますが、2 番目のケースではエラーがスローされることです。

:36: エラー: ')' が必要ですが、'.' です 見つかった。
                case ((d(カウンター)._1) == キー) => d(カウンター)._2

3番目も:

scala> case _ => カウンター += 1
:1: エラー: 定義の開始が不正です

しかし、それは2番目が正しくないためだと思います。私の最初の考えは、タプルを正しく比較していないということですが、タプルにインデックスを付けるための構文に従っているように見えるので、困惑しています。誰かが私を正しい方向に導くことができますか?

4

3 に答える 3

6

うまくいけば、あなたの混乱を解消するためにいくつかのことがあります:

scala でのマッチングは、次の一般的なテンプレートに従います。

x match {
  case SomethingThatXIs if(SomeCondition) => SomeExpression
  // rinse and repeat
  // note that `if(SomeCondition)` is optional
}

match/case 式を if/else if/else のようなブロックとして使用しようとしたようですが、私が知る限り、そのxブロック内では問題ではありません。その場合は、次のようなもので問題ないかもしれません

case _ if (d(counter)._1 == key) => d(counter)._2

しかし

Listscala の sに関する情報。LinkedListインデックス付きルックアップが操作である のように常に考える必要がありますO(n)head :: tailリストはフォーマットに一致させることができNil、空のリストです。例えば:

val myList = List(1,2,3,4)
myList match {
  case first :: theRest => 
    // first is 1, theRest is List(2,3,4), which you can also express as
    // 2 :: 3 :: 4 :: Nil
  case Nil =>
    // an empty list case
}

一種の ListMap を構築しているように見えるので、メソッドを実装するより「機能的」/「再帰的」な方法を書きますget

dそれがバッキングリストであると仮定しますList[(String, Any)]

def get(key: String): Option[Any] = {
  def recurse(key: String, list: List[(String, Any)]): Option[Any] = list match {
    case (k, value) :: _ if (key == k) => Some(value)
    case _ :: theRest => recurse(key, theRest)
    case Nil => None
  }
  recurse(key, d)
}

3 つのケース ステートメントは、次のように説明できます。

1) の最初の要素listは のタプルです(k, value)_この場合は気にしないため、リストの残りの部分は に一致します。条件は、k探しているキーと等しいかどうかを尋ねます。この場合、valueタプルから を返します。

2) 最初の要素には正しいキーがなかったので、再帰します。最初の要素は気にしませんが、再帰できるようにリストの残りが必要です。

3)case Nilリストに何もないことを意味し、「失敗」と再帰の終わりを示すはずです。この場合、 を返しNoneます。counter > accこれは、質問の状態と同じであると考えてください。

さらに詳しい説明が必要な場合は、遠慮なくお尋ねください。誤って間違いを犯した場合 (コンパイルできないなど) は、指摘して修正します。

于 2012-09-19T18:42:25.223 に答える
2

タプルのリストから条件付きでタプルの一部を抽出することがあなたの質問の重要な部分であると仮定しています.私が間違っていたらすみません.

まず第一に、Scala では通常、Object の代わりに AnyRef を使用するか、価値がある場合は、関数またはメソッドの再利用を増やし、型の安全性を高めることができる型パラメーターを使用します。

説明した 3 つのケースは 2 つのケースに折りたたむことができます。最初のケースはガード (パターン一致の後の if ステートメント) を使用し、2 番目のケースは空でないリスト全体に一致し、最初の各タプル引数とキー、一致するタプルの 2 番目のタプル引数を含む Some[T] を返すか、一致が発生しなかった場合は None を返します。検索操作はリストをトラバース (反復) するため、3 番目のケースは必要ありません。

検索後の map 操作は、2 番目のタプル引数を抽出するために使用され (Option の map は Option を返します)、この操作を削除し、タプル全体を返す場合は、メソッドの戻り値の型を Option[(String, T)] に変更します。

def f[T](key: String, xs: List[(String, T)], initialCount: Int = 2): Option[T] = {
  var counter = initialCount

  xs match {
    case l: List[(String, T)] if l.size < counter => None
    case l: List[(String, T)] => l find {_._1 == key} map {_._2}
  }
}

f("A", List(("A", 1), ("B", 2))) // Returns Some(1)
f("B", List(("A", 1), ("B", 2))) // Returns Some(2)
f("A", List(("A", 1)))           // Returns None
f("C", List(("A", 1), ("B", 2))) // Returns None
f("C", Nil)                      // Returns None
于 2012-09-19T21:18:19.017 に答える
0

まず、なぜListその理由で a を使用しているのですか? 必要なのは間違いなくMap. キーが見つからない場合、およびその中に見つかった場合はget()戻ります。NoneSome(value)

第二に、あなたの例には何がxありますか? リストですか?

case (log) => ..第三に、どこlogに論理条件があるかを書くことはできません。それはcase _ if (log) => ...(Rex Kerr がコメントで既に指摘しているように) の形式です。

第 4 に、これには再帰関数が必要です (単純にカウンターを増やすと、2 番目の要素でのみこれが呼び出されます)。

したがって、次のようなものが必要になります(それでも固執したい場合List):

def get(l: List[Tuple2[String, String]], key: String): Option[String] = {
    if (l.isEmpty) {
        None
    } else {
        val act = l.head
        act match {
            case x if (act._1 == key) => Some(act._2)
            case _ => get(l.tail, key)
        }
    }
}
于 2012-09-19T18:36:47.520 に答える