2012-03-08 1 views
4

Как сравнить два List<MyObject1> с List<MyObject2>? Итак, если значение Value имеет другое значение, его можно проверить.Как сравнить два `Список <MyObject1> со списком <MyObject2>`?

(я знаю, что мы можем использовать foreach ... Но я хотел бы LinQ решения /)

Спасибо!

public sealed class MyObject1 
{ 
    public string Name { get; set; } 

    public string Value { set; get; } 

    public Guid ID { get; set; } 
} 

public sealed class MyObject2 
{ 
    public string Name { get; set; } 

    public string Value { set; get; } 

    public Guid ID { get; set; } 
} 
+3

Что вы хотите сравнить? Списки или объекты в списках? – ChrisF

+0

@ChrisF Позвольте мне исправить свой вопрос pls ... Done –

+0

Перет перечисляет каждый объект в списке A и сравнивает его с каждым объектом в списке B. Проводка, которую вы пытались сделать, делает peoplel, как я, более охотно дающим вам больший намек. –

ответ

2
public class myComparer: IEqualityComparer 
{ 
    public new bool Equals(object x, object y) 
    { 
     if (x is string) 
     return x == y; 
     else if (x is Guid) // maybe you want them to be equal if last char is equal. so you can do it here. 
     return x == y; 
     else 
     return EqualityComparer<object>.Default.Equals(x, y); 
    } 

    public int GetHashCode(object obj) 
    { 
     return EqualityComparer<object>.Default.GetHashCode(obj); 
    } 
} 

Теперь

List<MyObject1 > lst1 = new MyObject1 <MyObject1 >(); 
//add items here... 

List<MyObject2 > lst2 = new MyObject1 <MyObject2 >(); 
//add items here... 

можно приравнять 2 способами:

IStructuralEquatable equ = lst1 ; 

    Console.WriteLine(equ.Equals(lst2 , EqualityComparer<object>.Default)); 

    or 

    Console.WriteLine(equ.Equals(lst2 , new myComparer())); 
+0

Что значит t1, t2 в вашем образце? Не могли бы вы объяснить это, пожалуйста? –

+0

IMO, это нехорошее решение. Типовое тестирование делает его дорогостоящим, и shoehorning все, чтобы возразить, чтобы вы могли использовать IEqualityComparer, слишком сложны пополам. – spender

+0

@spender, как долго они не работают в режиме наследования - у вас нет опции. если бы у них были отношения наследования, мы могли бы сделать что-то безопасное типа. но ОП не упоминал об этом. постскриптум посмотрите пример MSDN - точно так же, как myne: http://msdn.microsoft.com/en-us/library/system.collections.istructuralequatable.aspx они использовали TUPLES. –

7

Принятая ответ this SO question предлагает использовать Enumerable.SequenceEqual, документально here.

Метод принимает два IEnumerable s и IEqualityComparer. Он выполняет итерацию по обоим спискам параллельно и проверяет элемент равенства по элементу с помощью предоставленного вами компаратора.

В реализации IEqualityComparer вы можете сравнить экземпляры MyObject по своим свойствам идентификатора.

Если действительно есть два типа объекта, вы могли бы сделать что-то вроде MyList1.Select(new MyObject2 {/*mapping goes here*/}) или попробовать использовать AutoMapper

+1

Но IEqualityComparer используется для одного типа в то время –

+1

Обновлен мой ответ, чтобы справиться с этим. –

+0

+1, вот что я говорю;) –

2

Если вы не хотите (или не может) реализовать свои собственные IEqualityComparer, можно молнии и сравнения полей :

list1.Count == list2.Count 
&& list1 
    .Zip(list2, (i1,i2) => new{i1,i2}) 
    .All(x => x.i1.Name == x.i2.Name 
       && x.i1.Value == x.i2.Value 
       && x.i1.ID == x.i2.ID) 
+0

вся идея с *** rer - это когда вы не можете редактировать класс - поэтому вы используете другой класс. ваше предложение не является логическим '(или не может) реализовать ваш собственный IEqualityComparer' –

+0

Как насчет' list1.Zip (list2, (i1, i2) => i1.Name = i2.Name && i1.Value == i2.Value && i1.ID == i2.ID) .All() '? – Gabe

1

Ваши классы одинаковы, поэтому я считаю, что вы хотите сделать, это сравнить два списка объектов типа MyObject:

public class MyObject 
{ 
    public string Name { get; set; } 

    public string Value { set; get; } 

    public Guid ID { get; set; } 
} 

I найти самый простой способ сделать это, без необходимости писать отдельный IEqualityComparer, заключается в том, чтобы класс MyObject реализовал интерфейс IComparable. Это объясняется подробно halfway down this page, но это то, что ваш класс будет выглядеть после реализации интерфейса:

public class MyObject : IEquatable <MyObject > 
{ 
    public string Name { get; set; } 

    public string Value { set; get; } 

    public Guid ID { get; set; } 

    public bool Equals(MyObject other) 
    { 

    //Check whether the compared object is null. 
    if (Object.ReferenceEquals(other, null)) return false; 

    //Check whether the compared object references the same data. 
    if (Object.ReferenceEquals(this, other)) return true; 

    //Check whether the objects properties are equal. 
    return Name.Equals(other.Name) && Value.Equals(other.Value) && ID.Equals(other.ID); 
    } 

    public override int GetHashCode() 
    { 

    //Get hash code for the Name field if it is not null. 
    int hashName = Name == null ? 0 : Name.GetHashCode(); 

    //Get hash code for the Value field. 
    int hashCode = Value == null ? 0 : Value .GetHashCode(); 

    //Get hash code for the IDfield. 
    int hashID = ID.GetHashCode(); 

    //Calculate the hash code for the entire object. 
    return hashName^hashCode^hashId; 
    } 
} 

После того, как ваш класс имеет Equals() и GetHashCode() методы, метод LINQ Except() будет автоматически работать:

List<MyObject> objects1 = { new MyObject{ Name = "apple", Value= "fruit", ID= 9 }, 
          new MyObject{ Name = "orange", Value= "fruit", ID= 4 }, 
          new MyObject{ Name = "lemon", Value= "fruit", ID= 12 } }; 

List<MyObject> objects2 = { new MyObject { Name = "apple", Value= "fruit", ID= 9 } }; 

List<MyObject> comparison = objects1.Except(objects2); 

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

Смежные вопросы