2017-07-17 13 views
-1

質問が移動しましたhereDiffツールに似たクラスオブジェクトの2つのリストを比較する

私の要件は、模倣のdiffツールのようなプログラムを書くことです。はい、この目的を達成するライブラリとオープンソース・コードがかなりありますが、私は自分自身のcomparerを作成したいと思います。

ここが出発点です。私はこのようになりますのDataItemというクラスがあります。私は、これらのクラスオブジェクトの二つのリストを持っている

public class DataItem 
{ 
    public DataItem() { } 
    public DataItem(string d, string v) { Data = d; Value = v; } 

    public string Data { get; set; } 
    public string Value { get; set; } 
} 

を、のは、PREとPOSTそれらを呼び出すと、次のようにいくつかの例の値を取りましょう。 'データ'部分はリスト内で一意になります。

preList: (Data,Value) 
AAA,0 
BBB,1 
CCC,3 
DDD,4 
FFF,0 
GGG,3 

postList: (Data,Value) 
AAA,0 
BBB,2 
DDD,4 
EEE,9 
FFF,3 

PREを元のリストと考え、いくつかの変更を行った後にPOSTとします。私は2つを比較し、3つのカテゴリに分類したいと思います:

  1. 追加された項目 - 新しい「データ」がリストに追加された項目。
  2. 削除されたアイテム - アイテムがリストから削除されました。
  3. 差分項目 - 「データ」はPREリストとPOSTリストの両方にありますが、対応する「値」は異なります。分類時に

そこで、彼らは次のようになります。

Added Items: 
EEE,9 

Removed Items: 
CCC,3 
GGG,3 

Diff Items: 
BBB 
FFF 

は私が最終的な結果を入れたいそれらのオブジェクトに、別のDiffItemクラスを持っています。 DiffItemは次のようになります。

public class DiffItem 
{ 
    public DiffItem() { } 
    public DiffItem(string data, string type, string pre, string post) { Data = data; DiffType = type; PreVal = pre; PostVal = post; } 

    public string Data { get; set; } 
    public string DiffType { get; set; } // DiffType = Add/Remove/Diff 
    public string PreVal { get; set; } // preList value corresponding to Data item 
    public string PostVal { get; set; } // postList value corresponding to Data item 
} 

は、これを達成するために、最初に私がされたIEqualityComparerを拡張し、する比較器のカップルを書いた:その後除き使用

public class DataItemComparer : IEqualityComparer<DataItem> 
{ 
    public bool Equals(DataItem x, DataItem y) 
    { 
     return (string.Equals(x.Data, y.Data) && string.Equals(x.Value, y.Value)); 
    } 

    public int GetHashCode(DataItem obj) 
    { 
     return obj.Data.GetHashCode(); 
    } 
} 

public class DataItemDataComparer : IEqualityComparer<DataItem> 
{ 
    public bool Equals(DataItem x, DataItem y) 
    { 
     return string.Equals(x.Data, y.Data); 
    } 

    public int GetHashCode(DataItem obj) 
    { 
     return obj.Data.GetHashCode(); 
    } 
} 

()と交差()メソッドを次のように

static void DoDiff() 
    { 
     diffList = new List<DiffItem>(); 

     IEnumerable<DataItem> preOnly = preList.Except(postList, new DataItemComparer()); 
     IEnumerable<DataItem> postOnly = postList.Except(preList, new DataItemComparer()); 
     IEnumerable<DataItem> common = postList.Intersect(preList, new DataItemComparer()); 

     IEnumerable<DataItem> added = postOnly.Except(preOnly, new DataItemDataComparer()); 
     IEnumerable<DataItem> removed = preOnly.Except(postOnly, new DataItemDataComparer()); 
     IEnumerable<DataItem> diffPre = preOnly.Intersect(postOnly, new DataItemDataComparer()); 
     IEnumerable<DataItem> diffPost = postOnly.Intersect(preOnly, new DataItemDataComparer()); 

     foreach (DataItem add in added) 
     { 
      diffList.Add(new DiffItem(add.Data, "Add", null, add.Value)); 
     } 
     foreach (DataItem rem in removed) 
     { 
      diffList.Add(new DiffItem(rem.Data, "Remove", rem.Value, null)); 
     } 
     foreach (DataItem pre in diffPre) 
     { 
      DataItem post = diffPost.First(x => x.Data == pre.Data); 
      diffList.Add(new DiffItem(pre.Data, "Diff", pre.Value, post.Value)); 
     } 
    } 

これは機能し、ジョブが完了します。しかし、これを行うための「より良い」方法があるのだろうかと思っています。私はこれをより良くするための適切な定義を持っていないので、私は単語の周りに引用符を置くことに注意してください。おそらく、Linqの背後にはかなりの反復があると想像しているので、多くの 'foreach'ループとExcept()とIntersetc()の使用なしでこれを行う方法があります。

簡単に言えば、私はこれを書くことができるクリーナーコードがありますか?私は主に学問的な興味から欲しいと思っています。

+1

これは、より良い[コードレビュー](https://codereview.stackexchange.com/)に掲載されます。 – hatchet

+0

提案をありがとう!これをそこに移動することは可能でしょうか、削除してそこに投稿する必要がありますか? – Sach

+1

私はコードレビューサイトに移動したので、この質問をトピックとしてクローズすることにしました。 – Sach

答えて

0

私はあなたがたIEqualityComparerを必要とは思わない:

var added = from a in postList 
      where !preList.Any(b => b.Data == a.Data) 
      select new DiffItem(a.Data, "Add", null, a.Value); 
var removed = from b in preList 
       where !postList.Any(a => a.Data == b.Data) 
       select new DiffItem(b.Data, "Remove", b.Value, null); 
var diff = from b in preList 
      join a in postList on b.Data equals a.Data 
      where b.Value != a.Value 
      select new DiffItem(b.Data, "Diff", b.Data, a.Data); 
var diffList = added.ToList(); 
diffList.AddRange(removed); 
diffList.AddRange(diff); 
関連する問題