2013-06-21 35 views
1

我必須比較兩個包含另一個項目列表(稱爲圖表)的類型幻燈片列表。 我必須找到幻燈片清單,其中的差異可能是之間的所有差異:比較兩個列表,並獲取所有區別?

在列表A中的幻燈片,而不是B中

在列表A中的幻燈片,而不是B中

幻燈片在這兩個列表中,但它們的圖表不同

我嘗試使用except,但它返回具有不同圖表的列表爲「相同」。 示例 列表A:A B C D 列表B:A B C D *(d包含不同的圖表) 應該返回D *,但這不起作用。

我有點困惑,爲什麼發生這種情況 - 比較對我來說看起來不錯。

我的代碼:

class PPDetectDifferences 
{ 
    private PPPresentation laterVersion; 
    private string Path { get; set; } 

    private PPPresentation OriginalPresentation { get; set; } 

    private PPPresentation GetLaterPresentation() 
    { 
     var ppDal = new PPDAL(Path); 
     Task<PPPresentation> task = Task.Run(() => ppDal.GetPresentation()); 

     var presentation = task.Result; 
     return presentation; 
    } 

    public PPDetectDifferences(string path, PPPresentation ppPresentation) 
    { 
     if (path != null) 
     { 
      this.Path = path; 
     } 
     else 
     { 
      throw new ArgumentNullException("path"); 
     } 

     if (ppPresentation != null) 
     { 
      this.OriginalPresentation = ppPresentation; 
     } 
     else 
     { 
      throw new ArgumentNullException("ppPresentation"); 
     } 
    } 

    public bool IsDifferent() 
    { 
     //// getting the new List of Slides 
     laterVersion = GetLaterPresentation(); 

     //// Compare the newer version with the older version 
     var result = laterVersion.Slides.Except(OriginalPresentation.Slides, new PPSlideComparer()).ToList(); 

     //// If there are no differences, result.count should be 0, otherwise some other value. 
     return result.Count != 0; 
    } 
} 

/// <summary> 
/// Compares two Slides with each other 
/// </summary> 
public class PPSlideComparer : IEqualityComparer<PPSlide> 
{ 
    public int GetHashCode(PPSlide slide) 
    { 
     if (slide == null) 
     { 
      return 0; 
     } 
     //// ID is an INT, which is unique to this Slide 
     return slide.ID.GetHashCode(); 
    } 

    public bool Equals(PPSlide s1, PPSlide s2) 
    { 
     var s1Charts = (from x in s1.Charts select x).ToList(); 
     var s2Charts = (from x in s2.Charts select x).ToList(); 

     var result = s1Charts.Except(s2Charts, new PPChartComparer()).ToList(); 

     return result.Count == 0; 
    } 
} 

/// <summary> 
/// Compares two Charts with each other 
/// </summary> 
public class PPChartComparer : IEqualityComparer<PPChart> 
{ 
    public int GetHashCode(PPChart chart) 
    { 
     //// UID is an INT, which is unique to this chart 
     return chart == null ? 0 : chart.UID.GetHashCode(); 
    } 

    public bool Equals(PPChart c1, PPChart c2) 
    { 
     var rvalue = c1.UID == c2.UID; 

     if (c1.ChartType != c2.ChartType) 
     { 
      rvalue = false; 
     } 
     return rvalue; 
    } 
} 
+2

「一表A幻燈片,但不是在B」和 「中列出的滑動,但不是在B」是什麼是不同的? –

回答

1

要使用除了比較兩個序列,你需要檢查兩個方向。例如:

List<T> a, b; 
IEqualityComparer<T> cmp = ... 
var areEqual = !a.Except(b, cmp).Concat(b.Except(c, cmp)).Any(); 

此問題出現兩次,在你的代碼:首先,當你在比較的幻燈片2所列出並再次,當你比較圖表2名列表。

使用Except()進行收集比較時需要注意的另一件事是它用作集合操作。因此,{ A, A, A }.Except({ A })將返回空。

因此,我建議更多的東西像下面這樣:

public static bool CollectionEquals<T>(this ICollection<T> @this, ICollection<T> that, IEqualityComparer<T> cmp = null) 
{ 
    // to be equal, the 2 collections must not be null unless they're both null or have the same count 
    if (ReferenceEquals(@this, that)) { return true; } 
    if (@this == null || that == null) { return false; } 
    if (@this.Count != that.Count) { return false; } 

    // use the default comparer if one wasn't passed in 
    var comparer = cmp ?? EqualityComparer<T>.Default; 

    // to handle duplicates, we convert @this into a "bag" (a mapping 
    // from value -> # occurrences of that value in the collection 
    var thisDict = @this.GroupBy(t => t, comparer) 
     .ToDictionary(g => g.Key, g => g.Count(), comparer); 
    // do the same for that 
    var thatDict = @this.GroupBy(t => t, comparer) 
     .ToDictionary(g => g.Key, g => g.Count(), comparer); 

    // the two collections are equal if they have the same number of distinct values 
    return thisDict.Count == thatDict.Count 
     // and if, for each distinct value in @this, that value is also in that 
     // and has the same number of occurrences in @this and that 
     && thisDict.All(kvp => thatDict.ContainsKey(kvp.Key) 
         && thatDict[kvp.Key] == kvp.Value); 
} 
+1

你好,你能解釋一下你的代碼的作用嗎?我有點不知所措... –

+0

@ChristianSauer我已經添加了一些意見,以幫助澄清 – ChaseMedallion

+0

非常感謝! 對我來說非常好,特別是在開始時的理智檢查。我會用這個我想。 –

2

你比較似乎是錯誤的。如果您使用except比較列表,則必須以兩種方式執行此操作。

從MSDN:

「該方法返回的第一個未出現在第二這些元素它不還返回第二,不會出現在第一個的元素。」

在你的情況:

public bool Equals(PPSlide s1, PPSlide s2) 
{ 
    var s1Charts = (from x in s1.Charts select x).ToList(); 
    var s2Charts = (from x in s2.Charts select x).ToList(); 

    var result = s1Charts.Except(s2Charts, new PPChartComparer()).ToList(); 

    return result.Count == 0; 
} 

如果s1Charts具有比s2Charts然後result.Count> 0否則result.Count爲零更多元件。

速戰速決可能是:

var result2 = s2Charts.Except(s1Charts, new PPChartComparer()).ToList(); 

return result.Count == 0 and result2.Count == 0;