if によるフィルタリング
内包表記のガードです。
「if によるフィルタリング」はCoddyKit上の無料Scala for Backend Engineering & Functional Programmingレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはScala for Backend Engineering & Functional Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。
for-comprehensionのガード
for-comprehensionの中には、ガードと呼ばれるif条件を追加できます。filterと同じように、条件を満たす要素だけを残します。
object Main {
def main(args: Array[String]): Unit = {
val evens = for (x <- 1 to 10 if x % 2 == 0) yield x
println(evens)
}
}ガードはwithFilterに展開される
if condというガードは、withFilter(filterの遅延評価版)への呼び出しに書き換えられます。
for (x <- xs if p(x)) yield x- は
xs.withFilter(p).map(x => x)になります
object Main {
def main(args: Array[String]): Unit = {
val sugar = for (x <- List(1, 2, 3, 4) if x > 2) yield x
val desugared = List(1, 2, 3, 4).withFilter(_ > 2).map(x => x)
println(sugar == desugared)
}
}filterではなくwithFilterを使う理由
withFilterは遅延評価されるため、中間コレクションを作りません。条件は後続のmapまたはflatMapが実行されたときだけ適用されるので、メモリと処理を節約できます。
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4, 5, 6)
val result = for (n <- nums if n % 3 == 0) yield n * 100
println(result)
}
}複数のガード
複数のガードをチェーンできます。論理ANDのように組み合わされるため、要素が残るにはすべての条件を満たす必要があります。
object Main {
def main(args: Array[String]): Unit = {
val result = for {
x <- 1 to 20
if x % 2 == 0
if x % 3 == 0
} yield x
println(result)
}
}複数のジェネレーターに対するガード
ガードは任意のジェネレーターの後に置け、そのレベルの反復をフィルターします。テスト対象の値を生成するジェネレーターの直後にガードを置いてください。
object Main {
def main(args: Array[String]): Unit = {
val coprimeSums = for {
x <- 1 to 3
y <- 1 to 3
if x != y
} yield (x, y)
println(coprimeSums)
}
}ガードと値のバインディングを組み合わせる
ガード(if)と値のバインディング(=)は自由に組み合わせられます。順序が重要です。ガードより前に定義したバインディングは、そのガード内で使用できます。
object Main {
def main(args: Array[String]): Unit = {
val result = for {
x <- 1 to 6
square = x * x
if square > 10
} yield square
println(result)
}
}Stringコレクションに対するガード
ガードは数値だけでなく、任意の述語で動作します。ここでは単語を長さでフィルターしています。
object Main {
def main(args: Array[String]): Unit = {
val words = List("scala", "go", "java", "rust", "c")
val longWords = for (w <- words if w.length >= 4) yield w.toUpperCase
println(longWords)
}
}Optionsのフィルタリング
Optionでは、条件に合わないガードによって結果がNoneになります。これにより、for-comprehensionを使ってオプショナルな値を簡潔に検証できます。
object Main {
def main(args: Array[String]): Unit = {
val ok = for (x <- Some(8) if x > 5) yield x
val bad = for (x <- Some(3) if x > 5) yield x
println(ok)
println(bad)
}
}ガードの位置で意味が変わる
ガードからは、ガードより上で束縛された値しか参照できません。必要なジェネレーターより前に置くと、コンパイルできません。必ず、対象となるジェネレーターの後にガードを置いてください。
object Main {
def main(args: Array[String]): Unit = {
val result = for {
x <- 1 to 3
y <- 1 to 3
if x + y == 4
} yield s"$x + $y = ${x + y}"
result.foreach(println)
}
}ガードと最後のフィルターの違い
内包表記の後で結果をフィルタリングすることもできますが、ガードは反復の途中でフィルタリングします。ジェネレーターが複数ある場合、ガードによって早い段階で分岐を取り除けるため、全体の処理量を減らせます。
object Main {
def main(args: Array[String]): Unit = {
val withGuard = for {
x <- 1 to 100
if x % 25 == 0
} yield x
println(withGuard)
}
}読みやすい検証パイプライン
ガードを積み重ねると、条件のチェックリストのように読めます。これは、実際のScalaコードでfor内包表記を使う最も慣用的な方法の一つです。
object Main {
def main(args: Array[String]): Unit = {
val valid = for {
n <- List(4, 7, 12, 15, 20)
if n > 5
if n < 18
if n % 2 == 0
} yield n
println(valid)
}
}クイックチェック
for内包表記のガード(if)は、どのメソッド呼び出しに糖衣構文展開されますか?
まとめ
for内包表記のガードについて学びました。
if condは反復中に要素をフィルタリングします- ガードは
withFilter(遅延フィルタリング)に糖衣構文展開されます - 複数のガードは論理ANDのように組み合わされます
- ガードからは、その上で束縛された値しか参照できません
- ガードはジェネレーターや
=による束縛と自由に組み合わせられます
よくある質問
「if によるフィルタリング」レッスンは無料ですか?
はい。「if によるフィルタリング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Scala for Backend Engineering & Functional Programmingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。
「if によるフィルタリング」で何を学びますか?
内包表記のガードです。 ブラウザで直接実行するハンズオンコードでScala for Backend Engineering & Functional Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Scala for Backend Engineering & Functional Programmingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのScala for Backend Engineering & Functional Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「if によるフィルタリング」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このScala for Backend Engineering & Functional Programmingレッスンでコードを書いて実行できますか?
はい。すべてのScala for Backend Engineering & Functional Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- for の脱糖
- if によるフィルタリング
- 複数のジェネレーター
- Option と Future の利用