データの更新処理で、データがたくさんあるので差分を抽出して処理時間を節約したい
⇒ コレクションオブジェクトの差分を抽出する
※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");
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");
c# diff でググったら自分のゴミ記事がトップに出る(汗
というわけでまじめにdiffする方法を追記する
もちろん自前ではできないのでgoogle先生が作ってくれたライブラリ diff-match-patch を使う
https://github.com/google/diff-match-patch/wiki/Language:-C%23
nugetで取れる(pocketberserkerさん ありがとう)
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)
- パッチももらえる(試してない)
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();