1

Scala の List クラスにはindexWhereメソッドがあり、指定された述語 (存在しない場合は -1) に一致する List 要素の単一のインデックスを返します。

私は最近、特定の述語に一致するリスト内のすべてのインデックスを収集したいと考えており、次のような式を書いていることに気付きました。

list.zipWithIndex.filter({case (elem, _) => p(elem)}).map({case (_, index) => index})

ここpに、一致する要素を選択するための述語関数があります。これは、このような単純な要件に対しては扱いにくい表現のように思えます (ただし、1 つまたは 2 つのトリックが欠けている可能性があります)。

indicesWhere私は代わりに書くことを可能にする List 上の関数を見つけることを半分期待していました:

list.indicesWhere(p)

このようなものを Scala の List API の一部にする必要がありますか?それとも、同じことを行う上で示したものよりもはるかに単純な式がありますか?

4

2 に答える 2

4

さて、これは、あなたが持っている構文上のノイズの一部を削除する短い式です (Travis の提案を使用するように変更されています)。

list.zipWithIndex.collect { case (x, i) if p(x) => i }

または、次のようにします。

for ((x,i) <- list.zipWithIndex if p(x)) yield i

ただし、これを頻繁に使用する場合は、暗黙的なメソッドとして追加する必要があります。

class EnrichedWithIndicesWhere[T, CC[X] <: Seq[X]](xs: CC[T]) {
  def indicesWhere(p: T => Boolean)(implicit bf: CanBuildFrom[CC[T], Int, CC[Int]]): CC[Int] = {
    val b = bf()
    for ((x, i) <- xs.zipWithIndex if p(x)) b += i
    b.result
  }
}
implicit def enrichWithIndicesWhere[T, CC[X] <: Seq[X]](xs: CC[T]) = new EnrichedWithIndicesWhere(xs)

val list = List(1, 2, 3, 4, 5)
def p(i: Int) = i % 2 == 1
list.indicesWhere(p)         // List(0, 2, 4)
于 2012-12-28T17:11:04.630 に答える
3

unzip を使用してマップを置き換えることができます。

list.zipWithIndex.filter({case (elem, _) => p(elem)}).unzip._2
于 2012-12-28T16:35:33.247 に答える