Hello~! ミョウガです!
今回はF#のリストやシーケンスの結合を活用して、カレンダーを出力するプログラムを作成した時のお話です。
1. 1週目の空白スペース用と日付用でそれぞれリスト(シーケンス)を作成し、結合してみました
まず思いついたのが、「1日の曜日に合わせてオフセットするための空白スペース用」と「日付用」のリストを生成し、それらを結合して、各要素を出力するという方法です。
リストを結合する時は、リストの間に「@」を入れて、
[ リスト1 ] @ [ リスト2 ]
と書きます。
[<EntryPoint>]
let main argv =
// 現在の日付を取得し、当月1日の曜日と末日を求めます。
let now = System.DateTime.Today
let prePad = int( System.DateTime( now.Year, now.Month, 1 ).DayOfWeek )
let lastDay = System.DateTime.DaysInMonth( now.Year, now.Month )
// カレンダーを出力します。
// iはリストのインデックスであり、日曜始まりでです。dは日付もしくは空白スペースです。
// iの7の余剰が6、即ち土曜日であるもしくは月末日であれば、改行も出力します。
Seq.iteri ( fun i d -> printf ( if i % 7 = 6 || i + 1 = prePad + lastDay then "%s\n" else "%s" ) d )
// 1日のパディング部と日付(あらかじめ文字列に変換します)部のリストを連結し、カレンダー用リストを生成します。
( [ for i in 1..prePad -> " " ] @ [ for d in 1..lastDay -> System.String.Format( "{0, 3}", d ) ] )
0
※このプログラムはhttps://gist.github.com/Nia-TN1012/c3b6002fc9dba0af15c6611ba519e807でも公開されています(※GitHubアカウントの統合のため、ニア側のGistに移動しました)。
ここで重要なのが14行目の部分です。1週目の空白スペース用のリストの各要素は文字列型なので、日付用のリストもそれに合わせて各要素を文字列型にする必要があります。
ということで、リスト生成時にString.Formatメソッドで日付をあらかじめ書式指定文字列に変換しておきます。
あとは、12行目のSeq.iteri関数で各要素を出力するだけで、カレンダーが出来上がりますよっ♪
※なぜ、Seq.iteri関数を使用するかというと、土曜日での改行処理の条件判断にインデックス値を使用するからです。
2. 終わりに
今回はF#のリストやシーケンスの結合を活用して、カレンダーを出力するプログラムを作成しました。
次回は、パイプライン処理を活用したカレンダープログラミングのお話をしていきたいと思います。
[END]
コメント