2014年08月31日

C#でタブ区切りデータの処理

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その37

■問題 (出題者:ika さん)
タブ区切りのデータを読み込んで操作をし書き出す方法を教えてください。読み込み・書き出しの方法は任意とします。 与えられるデータは:
・レコードの区切りは改行、カラムの区切りはタブです。
・最初のレコードはヘッダで、カラムの名前が書いてあります。
・それ以降はデータで、第1,4カラムは整数値、第2,3カラムは文字列値です。

この入力データに対して以下の操作をしたものを書き出してください:

・第1カラムの値でデータを昇順にソートする。
・第2カラムと第3カラムをヘッダを含めて入れ替える。
・第4カラムの値にそれぞれ1を加える。

入力の例:
ID      Surname Forename        Age
1       Sato    Hanako  17
0       Suzuki  Taro    18
...

出力の例:
ID      Forename        Surname Age
0       Taro    Suzuki  19
1       Hanako  Sato    18
...

カラムの中にタブが含まれているときにどう表現するのかという問題は無視しています。
たぶん、そこまでは求めていないと思うので。
なので、String.Split()メソッド使えば、それほど難しいことはないですね。

それと、空のファイルのときの処理も入れてません。

LINQ to Objectの拡張機能である インタラクティブエクステンション(Interactive Extensions; Ix)のShare()メソドを使ったコードも書いてみました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Doukaku.Org {
    class Program {
        static void Main(string[] args) {
            {
                var lines = File.ReadAllLines("sample.tsv");

                var head = lines.First().Split('\t');
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                    head[0], head[2], head[1], head[3]);

                var body = lines.Skip(1)
                                .Select(s => s.Split('\t'))
                                .OrderBy(e => e[0]);
                foreach (var s in body) {
                    Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                        s[0], s[2], s[1], int.Parse(s[3]) + 1);
                }
            }
            {
                // Ix 使ってみた。あまり変わり映えしない...
                var lines = File.ReadAllLines("sample.tsv").Share();

                var head = lines.First().Split('\t');
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                    head[0], head[2], head[1], head[3]);

                var body = lines.Select(s => s.Split('\t'))
                                .OrderBy(e => e[0]);
                foreach (var s in body) {
                    Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                        s[0], s[2], s[1], int.Parse(s[3]) + 1);
                }

            }
        }
    }
}



 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/52381507