2013-06-21 4 views
1

Мне нужно сравнить два списка типа Slide, которые содержат другой Список элементов, называемых Charts. я должен найти все различия между слайд-листами, причем разница может быть:Сравните два списка и получите все различия?

слайда в списке А, но не в B

слайд в списке А, но не в B

a Слайд, который находится в обоих списках, но их Диаграммы разные

Я попытался использовать исключение, но он возвращает списки с разными диаграммами как «то же самое». Пример Список 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

«слайде в списке А, но не в 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;