2013年6月23日日曜日

テキストファイルを行番号付きでコンソールに出力する処理をLINQで。

タイトルの通り、テキストファイルを読み取ってコンソールに出力。その時に行番号を先頭に表示させる処理を考えてみます。

SJISのCSVファイルを各カラムの操作と条件による絞り込みを行い、UTF-8のCSVファイルを出力する処理をLINQで。」と同様に、TextReader/TextWriterをLINQで使いやすくする拡張メソッドを用意しておきます。
public static IEnumerable<string> GetLineEnumerator(this TextReader tr)
{
  string s;
  while ((s = tr.ReadLine()) != null)
  {
    yield return s;
  }
}

public static void WriteLines(
          this TextWriter tw, IEnumerable<string> values)
{
  foreach (var line in values)
  {
    tw.WriteLine(line);
  }
}

で、出力時に行番号を付ける方法を考えます。LINQっぽく考えれば、行番号は1から順番の数字が必要となるので、Enumerable.Rangeが使えそう。そして、行番号と入力した各ラインをそれぞれ順次送り出せればよいので、Enumerable.Zipで纏めるのがよさそう。

ってことで、前述の2つの拡張メソッドも使い、こんなコードになりました。
static void Main(string[] args)
{
  using(var reader = new StreamReader(args[0]))
  {
    Console.Out.WriteLines(Enumerable.Range(1, int.MaxValue)
      .Zip(reader.GetLineEnumerator(), Tuple.Create)
      .Select(x => string.Format("{0}:{1}", x.Item1, x.Item2)));
  }
}

0 件のコメント:

コメントを投稿