2015-02-08 3 views
1

Я пытаюсь обмануть массив объектов, используя два столбца, где второй столбец является Словарем. Лучший способ описать это показать код:LINQ и удаление дубликатов из массива объектов

class MyClass 
    { 
     public int ID; 
     public Dictionary<int, int> Dict = new Dictionary<int, int>(); 
    } 

И теперь, чтобы создать некоторые объекты:

 List<MyClass> list = new List<MyClass>(); 
     MyClass mc1 = new MyClass(); 
     list.Add(mc1); mc1.ID = 1; mc1.Dict.Add(1, 1); 

     MyClass mc2 = new MyClass(); 
     list.Add(mc2); mc2.ID = 1; mc2.Dict.Add(1, 1); 

     MyClass mc3 = new MyClass(); 
     list.Add(mc3); mc3.ID = 1; mc3.Dict.Add(1, 2); 

     MyClass mc4 = new MyClass(); 
     list.Add(mc4); mc4.ID = 2; mc4.Dict.Add(1, 1); 

Что я ищу, чтобы выполнить это отличается от ID и Dict. Результаты должны выглядеть следующим образом:

Список объектов MyClass (не симпатичных)

1  //MyClass.ID 
1,1 //MyClass.Dictionary 

1 
1,2 

2 
1,1 

Обратите внимание, что один из объектов был исключен из первоначального списка, потому что это был дубликат ID и Dict (словарные значения) , Я играл с альтернативными версиями:

 var s = from p in list 
       group p by p.ID into group1 
       from group2 in 
        (from p in group1 group p by p.Dict) 
       group group2 by group1.Key; 

но просто не повезло. Признайте, что любые люди, которые могут понять, могут решить эту проблему.

PS - Я не изменяю правила, но считаю, что GROUP BY и SELECTFIRST будут чище, чем DISTINCT, с дополнительным кодом для Comparer. Похлопывание по спине для тех, кто может понять это, используя GROUP BY.

ответ

0

Для ссылочных типов вы должны добавить equality comparer, чтобы сделать то, что хотите. Добавьте следующий класс:

public class MyClassComparer : IEqualityComparer<MyClass> 
    { 
     public bool Equals(MyClass left, MyClass right) 
     { 
      if (left == null && right == null) 
      { 
       return true; 
      } 
      if (left == null || right == null) 
      { 
       return false; 
      } 

      if (left.ID == right.ID) 
      { 
       if (left.Dict == null && right.Dict == null) 
       { 
        return true; 
       } 
       if (left.Dict == null || right.Dict == null) 
       { 
        return false; 
       } 
       if (left.Dict.Count != right.Dict.Count) 
       { 
        return false; 
       } 

       foreach(var key in left.Dict.Keys) 
       { 
        if(!right.Dict.ContainsKey(key)) 
         return false; 

        if (left.Dict[key] != right.Dict[key]) 
        return false; 
       } 

       return true; 
      } 
      else return false; 
     } 

     public int GetHashCode(MyClass author) 
     { 
      return (author.ID).GetHashCode(); 
     } 
    } 

И использовать этот компаратор в Distinct переопределения:

List<MyClass> list = new List<MyClass>(); 
MyClass mc1 = new MyClass(); 
list.Add(mc1); mc1.ID = 1; mc1.Dict.Add(1, 1); 

MyClass mc2 = new MyClass(); 
list.Add(mc2); mc2.ID = 1; mc2.Dict.Add(1, 1); 

MyClass mc3 = new MyClass(); 
list.Add(mc3); mc3.ID = 1; mc3.Dict.Add(1, 2); 

MyClass mc4 = new MyClass(); 
list.Add(mc4); mc4.ID = 2; mc4.Dict.Add(1, 1); 


var result = list.Distinct(new MyClassComparer()).ToList(); 

Вы должны улучшить GetHashCode метод. Это будет ваша домашняя работа :)

0

Могу ли я получить половину похлопывания за следующее? :)

var filteredList = list.GroupBy(mc => mc.ID) 
         .SelectMany(gr => gr.Distinct(new MyClassComparer())) 
         .ToList(); 

Comparer:

public class MyClassComparer : IEqualityComparer<MyClass> 
{ 
    public bool Equals(MyClass a, MyClass b) 
    { 
     return a.Dict.Count == b.Dict.Count && !a.Dict.Except(b.Dict).Any(); 
    } 


    public int GetHashCode(MyClass a) 
    { 
     return a.ID; 
    } 
} 
Смежные вопросы