LoginSignup
7
8

More than 3 years have passed since last update.

C#でdiffしたい(データ差分を抽出したい)

Last updated at Posted at 2018-06-11

データの更新処理で、データがたくさんあるので差分を抽出して処理時間を節約したい
⇒ コレクションオブジェクトの差分を抽出する

※diffをしたいと言ったが、本物のdiffのようなデータの場所が変わっても追跡するようなものは求めていない
今回は単純に配列の変更前後のdiffが取れればよい。可変配列ではなく固定配列の比較である。

LinqのExceptメソッド

2つのシーケンスの差集合を返すメソッド
差分は取れるが、インデックスがないので、どこのデータが変わったかわからない

var refer  = new object[]{1,  "b", "c","d",  null};
var target = new object[]{"a","b",true,"D","hoge"};

var exp = target.Except(refer)
    .Dump("Except");

image.png

LinqでIndex付きSelectしてEqualする

var refer  = new object[]{1,  "b", "c","d",  null};
var target = new object[]{"a","b",true,"D","hoge"};

var dif = target
    .Select( (v,idx) => v.Equals(refer[idx]) ? "" : v) //差分なしは何を返せばいいのか? nullは嫌だ
    .Dump("myDiff");

image.png


c# diff でググったら自分のゴミ記事がトップに出る(汗
というわけでまじめにdiffする方法を追記する

image.png

もちろん自前ではできないのでgoogle先生が作ってくれたライブラリ diff-match-patch を使う
https://github.com/google/diff-match-patch/wiki/Language:-C%23
nugetで取れる(pocketberserkerさん ありがとう)
image.png
https://github.com/pocketberserker/Diff.Match.Patch

diff-match-patchの使い方

比較したいテキストを2つ与えるだけでOK

    var dmp = DiffMatchPatchModule.Default;
    var diffs = dmp.DiffMain(text1,text2);
    var html = dmp.DiffPrettyHtml(diffs);

LINQPadで使ってみた

 3Dプリンタtrinus向けのgcodeをレーザー出力に変えたい
※gcode改造はまだ完成していない。差分が見たいなと思ってググったら自分の記事がトップに・・・

使ってみた結果は以下

  • 差分を可視化したHTMLがもらえる
  • 比較結果のリストがもらえる(Delete,Equal,Insert)
  • パッチももらえる(試してない)

image.png

image.png

LINQPadの実行コード

Func<string[], IEnumerable<string>> throwDontNeeds = (ss) => {

    var needs = ss.ToList().FindAll(f =>
    !f.StartsWith(";   ", StringComparison.Ordinal)
    && !f.StartsWith("M106", StringComparison.Ordinal)
    && !f.StartsWith("M140", StringComparison.Ordinal)
    && !f.StartsWith("M190", StringComparison.Ordinal)
    && !f.StartsWith("M104", StringComparison.Ordinal)
    && !f.StartsWith("M109", StringComparison.Ordinal)
    && !f.StartsWith("G1 E", StringComparison.Ordinal)
    );

    var reps = needs.Select(s =>
        Regex.Replace(s, "E.*|F.*", "")
        + (s.StartsWith("G1")?"E60":"")
    );

    var dmp = DiffMatchPatchModule.Default;
    var diffs = dmp.DiffMain(string.Join(Environment.NewLine, needs), string.Join(Environment.NewLine, reps));
    var html = dmp.DiffPrettyHtml(diffs);

    diffs.Dump();
    Util.RawHtml(html).Dump();

    return reps;
};

var gcodes = throwDontNeeds(
    File.ReadAllLines(@"C:\Users\wato\Documents\_work\eda\ex127.gcode")
).Dump();
7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8