※この記事はSwift by Sundellの内容を日本語に翻訳したものです。
ArrayやSetなどのコレクションを反復処理する場合、最初は、従来のforループを使用するか、クロージャーベースのforEachメソッドを使用するかは、好みとスタイルの問題のように思われるかもしれません。これらの2つのメカニズムが非常に類似していることは確かですが、いくつかの点で異なります。
これらの違いの1つは、forループの反復がコードの制御フロー内で直接実行されることです。これにより、これらの反復をより正確に制御できます。たとえば、continueキーワードを使用して任意の時点で次の要素にスキップするか、breakを使用して反復を完全に中断するかを選択できます。
func recentArticles(among articles: [Article]) -> [Article] {
var results = [Article]()
for article in articles {
guard !article.isDraft else {
// すぐに次の要素にスキップします。
continue
}
results.append(article)
guard results.count < 5 else {
// 反復を中断します。この場合、ここに直接戻ることもできます。
break
}
}
return results
}
forループの反復が(上記のように)フィルタリングに使用されるguard(またはif)ステートメントで始まる場合、代わりにwhereベースのパターンマッチングを使用してそのロジックを実装することもできます—次のように:
for article in articles where !article.isDraft {
results.append(article)
guard results.count < 5 else {
break
}
}
上記の種類の制御フロー関連の機能は、forループを非常に強力にする大きな部分ですが、そのレベルの制御が必要ない場合は、forEachの呼び出しを使用すると、コードが少し単純に見える可能性があります。たとえば、ここでは、配列の要素ごとに新しいビューを追加しています。これは、forEachを使用して非常にエレガントに実行できます。
func addArticleViews(for articles: [Article]) {
articles.forEach { article in
let articleView = ArticleView()
// クロージャーの article を使用して新しいビューを設定します。
...
view.addSubview(articleView)
}
}
ただし、Swiftのファーストクラス関数機能を使用する方がおそらくさらにエレガントです。上記のメソッドをリファクタリングして単一のArticleのみを受け入れ、そのメソッドをforEachの呼び出しに直接挿入します。
class ArticleGroupViewController: UIViewController {
private let articles: [Article]
...
override func viewDidLoad() {
super.viewDidLoad()
...
articles.forEach(addArticleView)
}
private func addArticleView(for article: Article) {
let articleView = ArticleView()
...
view.addSubview(articleView)
}
}
要約すると、forループを使用すると、反復をより高度に制御できます。一方、forEachを使用すると、一度開始すると反復を停止することはできませんが、クロージャとファーストクラス関数の機能を利用できます(エラーをスローすることは別として)。
元の記事
Picking between a for loop and forEach Swift by Sundell