Hatena::ブログ(Diary)

けさらんぱさらん Twitter

2012-04-22

LINQでファイルの差分を抽出する

LINQでファイルの差分を抽出したいと思います。

file01とfile02があります。
こんな感じ

file01

00000001,a,b,c,d,e,f,g
00000002,a,b,c,d,e,f,g
00000003,a,b,c,d,e,f,g
00000004,a,b,c,d,e,f,g
00000005,a,b,c,d,e,f,g
00000006,a,b,c,d,e,f,g
00000007,a,b,c,d,e,f,g
00000008,a,b,c,d,e,f,g
00000009,a,b,c,d,e,f,g
00000010,a,b,c,d,e,f,g

file02

00000001,a,b,c,d,e,f,h
00000002,a,b,c,d,e,f,i
00000003,a,b,c,d,e,f,g
00000004,a,b,c,d,e,f,g
00000005,a,b,c,d,e,f,g
00000006,a,b,c,d,e,f,g
00000007,a,b,c,d,e,f,g
00000008,a,b,c,d,e,f,g
00000009,a,b,c,d,e,f,g
00000011,a,b,c,d,e,f,g

ファイルには、同じ行もあれば更新されている行もあります。
最初のカラムがIDとなっています。
追加されている行も削除されている行もあります。
追加と削除は、同じIDがあるかどうかで判断します。

これを差分で出してファイルに書き出します。
書き出すファイルには、更新・追加・削除が分かるようにマークをつけます。

以下が、それを処理するコードです。

class Program
{
    static void Main( string[] args )
    {
        var lines1 = File.ReadLines( "file01.csv").ToList();
        var lines2 = File.ReadLines( "file02.csv").ToList();

        var timer =  new System.Diagnostics.Stopwatch();
        timer.Start();

        var tempAddData = lines2.Except( lines1, new ExistsCompare() );
        var file2Minus = lines2.Except( tempAddData );
        var tempDeleteData = lines1.Except( lines2, new ExistsCompare() );
        var file1Minus = lines1.Except( tempDeleteData );
        var tempUpdateData = file2Minus.Except( file1Minus);

        var addData = tempAddData.Select( l => l + ",insert" );
        var deleteData = tempDeleteData.Select( l => l + ",delete" );
        var updateData = tempUpdateData.Select( l => l + ",update" );

        File.WriteAllLines( "file03.csv", addData.Concat( deleteData ).Concat( updateData ) );

        timer.Stop();

        Console.WriteLine( timer.ElapsedMilliseconds );
        Console.ReadLine();
    }
}

// 頭の8桁だけで同一判定する
class ExistsCompare : IEqualityComparer<string>
{

    public bool Equals( string x, string y )
    {
        return x.Substring( 0, 8 ) == y.Substring( 0, 8 );
    }

    public int GetHashCode( string obj )
    {
        return obj.Substring(0,8).GetHashCode();
    }
}

結果はこんな感じのファイルが出力されます。

00000011,a,b,c,d,e,f,g,insert
00000010,a,b,c,d,e,f,g,delete
00000001,a,b,c,d,e,f,h,update
00000002,a,b,c,d,e,f,i,update

これより効率的にすっきり書く方法ってないですかね?

投稿したコメントは管理者が承認するまで公開されません。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

リンク元