パイプラインの構築
CoddyのSwiftジャーニー「ロジックとフロー」セクションの一部 — レッスン 31/56。
これまでに学んだメソッド、map、filter、reduce、compactMap、flatMap、sorted(by:)は、Swiftにおける日常的なツールキットです。実際のコードでは、これらを組み合わせて使用します。
struct Order {
let item: String
let qty: Int
}
let orders = [Order(item: "apple", qty: 3), Order(item: "bread", qty: 0), Order(item: "milk", qty: 5)]
let names = orders
.filter { $0.qty > 0 }
.sorted { $0.qty > $1.qty }
.map { $0.item }
print(names) // ["milk", "apple"]チェーンを上から下に読みます。空ではない注文を保持し、数量の降順で並べ替え、名前のみを抽出します。
パイプラインは、各ステップが1つの目的を持っているときに真価を発揮します。もしクロージャの中で2つのことを同時に行っている(マッピングとフィルタリングなど)ことに気づいたら、それらを2つのステップに分割しましょう。そうすることで、チェーンが長くなっても可読性が保たれます。
チャレンジ
中級1行の入力を読み込みます。これは name:price:qty 形式のエントリをカンマで区切ったリストです。一部のエントリは形式が正しくないため、スキップする必要があります。価格(price)または数量(qty)が有効な整数でないエントリはすべてスキップしてください。
qty > 0 である 有効な エントリごとに1行を出力するパイプラインを構築します。合計(price * qty)の 降順 でソートし、以下の形式で出力してください:
<name>: <total>各アイテムの行の後に、総計を示すサマリー行を1行 Sum: <n> の形式で出力してください。
入力が apple:3:2,bread:bad:1,milk:4:5,cheese:8:0,salt:2:7 の場合、出力は以下のようになります:
milk: 20
salt: 14
apple: 6
Sum: 40チートシート
高階関数を連結(チェイン)させることで、各ステップが1つの目的を持つ、可読性の高いパイプラインを作成できます。
let names = orders
.filter { $0.qty > 0 }
.sorted { $0.qty > $1.qty }
.map { $0.item }
一般的なパイプラインメソッド:filter → compactMap → sorted(by:) → map → reduce。もしクロージャが一度に2つのこと(例:マッピングとフィルタリング)を行っている場合は、2つのステップに分割してください。
自分で試してみよう
let entries = readLine()!.components(separatedBy: ",")
// TODO: compactMap (解析)、filter (数量 > 0)、
// sorted (合計の降順)、map (フォーマット) を使用したパイプライン。各行と合計を出力。
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。