2017-07-07 9 views
0

私はベクトルのベクトルで文字を検索する必要があります。私は非常に粗悪な方法を書いています。ベクトルのベクトルの要素を検索するためのより良い方法は何ですか?ここでスカラーのベクトルのベクトルの文字を検索するための良い方法

は私のコードです:ここでは

def search(xs: Vector[Vector[Char]], char: Char, rowIndex: Int): Pos = xs.headOption match { 
    case None => Pos(-1, -1) 
    case Some(row) => { 
    val tuple = searchHelper(row, char, 0) 
    if(tuple._1) 
     Pos(rowIndex, tuple._2) 
    else 
     search(xs.tail, char, rowIndex +1) 
    } 
} 

def searchHelper(xs: Vector[Char], char: Char, colIndex: Int): (Boolean, Int) = xs.headOption match { 
    case None => (false, colIndex) 
    case Some(col) => 
    if(col == char) 
     (true, colIndex) 
    else 
     searchHelper(xs.tail, char, colIndex +1) 
} 

search(vector, c, 0) 

は、入力された:

val input = 
    """ooo------- 
    |oSoooo---- 
    |ooooooooo- 
    |-ooooooooo 
    |-----ooToo 
    |------ooo-""".stripMargin 

val vector = 
    Vector(input.split("\n").map(str => Vector(str: _*)): _*) 

val c = 'S' 
+2

私はCourseraの割り当てを認識しているので、私はまっすぐな答えを出すつもりはありませんが、行インデックスと列インデックスの2つの異なるインデックス値を探しています。 [標準ライブラリ](http://www.scala-lang.org/api/current/scala/collection/immutable/Vector.html)は、コレクションからインデックスを抽出するためのいくつかの異なる方法を提供しています。これらのうち2つ(コメントヒントで述べたように)を使用すると、 'findChar()'チャレンジは2行のコードで解決できます。 – jwvh

+0

ありがとう。ちょうどヒントが必要でした。 – kromastorm

答えて

2

良くて、あなたはより簡潔な意味、場合、あなたはScalasコレクションのメソッドを活用してみてください:

これは、その文字が最初に出現する必要があることを前提としています。

indexWhereは、innerIndexが-1より大きいとすぐに終了します。おそらく

@tailrec 
def search(xs: Vector[Vector[Char]], c: Char, n: Int = 0): (Int, Int) = { 
    if (n > xs.size - 1) (-1, -1) 
    else 
    xs(n).indexOf(c) match { 
     case -1 => search(xs, c, n + 1) 
     case i => (n, i) 
    } 
} 
+0

ありがとうございます。私はこのコードを理解し、自分のバージョンを作成しようとします。 – kromastorm

+0

ew、可変vars! – Dima

+0

@Dima 1. innerIndexを取得するか、別の答えを提供するためのより良いオプションを提案してください。 2.関数から状態が漏れていないので、ここでは問題は見えません。 – thwiegan

2

このような何か、:

(および可変VARなし)だけでなく、最小限の反復であなたの再帰的な方向でより多くを行くかもしれないもう一つの可能​​性は、?

xs 
.iterator 
.zipWithIndex 
.map { case (chars, idx) => (chars, idx, chars.indexOf(c)) } 
.collectFirst { 
    case (chars, outer, inner) if(inner >= 0) => Pos(outer, inner) 
}.getOrElse(Pos(-1, 1)) 

コメントからの懸念に対処するために:これはないです(限り、それが一致先に見つかったとしてではなく、一度も完全に)リスト全体を複数回反復します。スカライテレータは素晴らしい方法です:概念的には、リスト全体への連続的な変換のように見えますが、実際には要素ごとに遅延的に実行される一連の呼び出しを書くことができます。最初の要素はリストから抽出され、 (chars, 0)mapに与えられ、その結果はcollectFirstに送られます。条件がそこに一致するならば、直ちに停止して戻ります。そうでなければ、次の要素がリストから取り出され、タプル(chars, 1)に与えられ、 .mapなど

+0

あなたは完全な外側のベクトル(2回)を反復しています+あなたはそれぞれの内側のベクトルの中のcharを探しています。次に、あなたがあなたのマッチを見つけるまで外側のベクトル上で再び繰り返します。私がindexWhereとvarableでこれを行った理由はありました;)反復の量を減らすためです。 – thwiegan

+1

いいえ、私は完全なベクトルを繰り返しているわけではありません。 2回ではなく、1回でもありません。それは、 'iterator'呼び出しがあるところです。 Scalaイテレータは怠惰です。ですから、技術的に '.iterator'はここでも必要ではありません(' zipWithIndex'は既にイテレータを返しています)、すべての反復が怠惰であることを明らかにするためにそこに出力します。 – Dima

+0

さて、私の悪い。 zipWithIndexがイテレータを返すのは確かですか? Scala replは、私のためにインデックスされたベクトル全体を返します。 – thwiegan

関連する問題