2012-01-20 15 views
6

マップとヌルスキップが1回の呼び出しで表現されるように、次のコードを表現できますか?Scalaでのマップとフィルタのヌルの組み合わせ

list.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null) 
+0

を 'その_.accept(この、引数) ''ヌル 'を返すことができます。この場合、少し慣れています(2つの呼び出しがありますが)。 'list.map(i => Option(i.accept(this、arg).asInstanceOf [T]))。flatten' –

+1

私は、間違っていますが、 'map'と' filter'の組み合わせを 'collect'していませんか?それとも別の方法でしたか?それとも、私は間違っていますか? ;) – agilesteel

+1

@agilesteel、はい、コレクトが機能するかもしれません。コードスニペットを投稿できますか? –

答えて

11
list flatMap { i => Option(i.accept(this, arg).asInstanceOf[T]) } 

または代わりに、あなたが好きならば、(これはより多くのまたはあなたの元の式にはあまり変換されますが)

for { 
    item <- list 
    itemConverted = item.accept(this, arg).asInstanceOf[T] 
    itemNonNull = itemConverted if itemConverted != 0 
} yield itemNonNull 

collectを使用することも可能であろうが、それはおそらく二回acceptを呼ぶだろうほとんどの議論では、部分関数のテストのために:

list collect { 
    case i if i.accept(this, arg).asInstanceOf[T] != null => i.accept(this, arg).asInstanceOf[T] 
} 

これを避けるには、メモ帳(またはスマートエクストラクタ)を使う必要があります。

+0

答えに感謝します! –

6

パフォーマンスを懸念している場合は、.view

list.view.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null) 

viewを追加することができますので、mapfilterはリスト上の1回のパスではなく、二つの別々のパスで実行されます、トラバーサルは怠惰になるようにします。あなたはこのパターンを再利用する懸念がある場合

、独自のヘルパー関数を定義することができます:私は推測

def mapNN[A,B](list: List[A])(f: A => B) = { 
    list.view.map(f(_)).filter(_ != null) 
} 

mapNN(list)(_.accept(this, arg).asInstanceOf[T]) 

テスト...

> mapNN(List(1,2,3))(x => if (x%2==0) x else null).toList 
res7: List[Any] = List(2) 
+0

この部分についてもっと説明できますか?マップとフィルタは、2回の別々のパスではなく、1回のパスで実行されるでしょうか?どのようにして2つの変換を適用するには1つのパスしか必要ないのですか? –

+1

@MinhThai 'view'についてまともな説明があります:https://stackoverflow.com/a/6799739/208257 基本的に、それは変換を怠惰にします。 'toList'を呼び出すまで、一回のパスでさえも遅延させます。その時点で、一回のパスで各変換を段階的に適用します。 –

関連する問題