2013-05-11 31 views
5

Tôi có hai Lists. Tôi muốn nhận các giá trị được đối sánh và chưa khớp dựa trên ID và thêm kết quả vào một số khác List. Tôi có thể nhận được cả hai trong số này bằng cách sử dụng Intersect/Except.Cách sao chép Danh sách <> sang Danh sách khác <> bằng Comparsion trong C#

Nhưng tôi chỉ có thể nhận được ID trong các biến kết quả (khớp và chưa khớp). Tôi cần tất cả các thuộc tính trong Bản mẫu.

List<Template> listForTemplate = new List<Template>(); 
List<Template1> listForTemplate1 = new List<Template1>(); 

var matches = listForTemplate .Select(f => f.ID) 
         .Intersect(listForTemplate1 .Select(b => b.ID)); 

var ummatches = listForTemplate .Select(f => f.ID) 
        .Except(listForTemplate1.Select(b => b.ID)); 

    public class Template 
    { 
     public string ID{ get; set; } 
     public string Name{ get; set; } 
     public string Age{ get; set; } 
     public string Place{ get; set; } 
     public string City{ get; set; } 
     public string State{ get; set; } 
     public string Country{ get; set; } 
    } 
    public class Template1 
    { 
     public string ID{ get; set; } 
    } 

Trả lời

3

Nếu bạn không muốn thực hiện IEquality cho nhiệm vụ đơn giản này, bạn chỉ có thể sửa đổi LINQ truy vấn của bạn:

var matches = listForTemplate.Where(f => listForTemplate1.Any(b => b.ID == f.ID)); 

var unmatches = listForTemplate.Where(f => listForTemplate1.All(b => b.ID != f.ID)); 

Bạn có thể muốn để kiểm tra null trước khi truy cập ID, nhưng nó sẽ hoạt động.

+0

Tôi chỉ nhận được trường ID (không phải tất cả) cho các kết quả phù hợp và chưa khớp Tôi cần tất cả các thuộc tính.Bất kỳ trợ giúp nào! –

+0

Nếu bạn muốn so sánh với tất cả các thuộc tính thì bạn sẽ cần phải thực hiện 'IEqualityComparer ' – Ric

+0

Tôi không muốn so sánh với tất cả các thuộc tính. Chỉ cần so sánh với một thuộc tính (ID) và nhận tất cả các thuộc tính trong một danh sách khác –

2

Bạn đang tìm hàm quá tải, với tham số thứ hai IEqualityComparer. Vì vậy, hãy so sánh của bạn (ví dụ: http://www.blackwasp.co.uk/IEqualityComparer.aspx) và sử dụng cùng một bộ so sánh trong giao cắt/ngoại trừ.

Và đối với phần chung: có thể bạn nên có giao diện chung cho mẫu, ví dụ: ObjectWithID mô tả rằng lớp có thuộc tính chuỗi ID. Hoặc chỉ đơn giản là sử dụng năng động trong so sánh của bạn (nhưng tôi nghĩ rằng đây là rất-rất antipattern bởi vì bạn có thể có lỗi thời gian chạy nếu sử dụng cho các loại xấu).

Bạn cũng gặp sự cố: giao nhau hai bộ sưu tập với hai loại khác nhau sẽ dẫn đến tập hợp đối tượng (lớp cha mẹ chung). Sau đó, bạn phải đúc rất nhiều (antipattern). Tôi khuyên bạn nên tạo một lớp/giao diện trừu tượng chung cho các lớp mẫu của bạn và nó đang hoạt động. Nếu bạn cần phải cast các yếu tố trở lại, không đúc, nhưng sử dụng các mô hình visitior: http://en.wikipedia.org/wiki/Visitor_pattern

Ví dụ (tốt):

static void Main(string[] args) 
    { 
     // http://stackoverflow.com/questions/16496998/how-to-copy-a-list-to-another-list-with-comparsion-in-c-sharp 

     List<Template> listForTemplate = new Template[] { 
      new Template(){ID = "1"}, 
      new Template(){ID = "2"}, 
      new Template(){ID = "3"}, 
      new Template(){ID = "4"}, 
      new Template(){ID = "5"}, 
      new Template(){ID = "6"}, 
     }.ToList(); 

     List<Template1> listForTemplate1 = new Template1[] { 
      new Template1(){ID = "1"}, 
      new Template1(){ID = "3"}, 
      new Template1(){ID = "5"} 
     }.ToList(); 

     var comp = new ObjectWithIDComparer(); 

     var matches = listForTemplate.Intersect(listForTemplate1, comp); 
     var ummatches = listForTemplate.Except(listForTemplate1, comp); 

     Console.WriteLine("Matches:"); 
     foreach (var item in matches) // note that item is instance of ObjectWithID 
     { 
      Console.WriteLine("{0}", item.ID); 
     } 
     Console.WriteLine(); 

     Console.WriteLine("Ummatches:"); 
     foreach (var item in ummatches) // note that item is instance of ObjectWithID 
     { 
      Console.WriteLine("{0}", item.ID); 
     } 
     Console.WriteLine(); 
    } 
} 

public class ObjectWithIDComparer : IEqualityComparer<ObjectWithID> 
{ 
    public bool Equals(ObjectWithID x, ObjectWithID y) 
    { 
     return x.ID == y.ID; 
    } 

    public int GetHashCode(ObjectWithID obj) 
    { 
     return obj.ID.GetHashCode(); 
    } 
} 

public interface ObjectWithID { 
    string ID { get; set; } 
} 

public class Template : ObjectWithID 
{ 
    public string ID { get; set; } 
    public string Name { get; set; } 
    public string Age { get; set; } 
    public string Place { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public string Country { get; set; } 
} 
public class Template1 : ObjectWithID 
{ 
    public string ID { get; set; } 
} 

Output:

Matches: 
1 
3 
5 

Ummatches: 
2 
4 
6 

Press any key to continue . . . 
+0

Ví dụ hay, đặc biệt là đưa nó cùng với giao diện. – Ric

0

Như đã đề cập, Thực hiện Giao diện IEqualityComparer<T>.

IEqualityComparer<T> MSDN

Sau đó sử dụng điều này như một cuộc tranh cãi trong phương pháp của bạn cho Except()Intersect()

Intersect

Có một ví dụ tốt về cách làm như vậy vào liên kết đối với phương pháp Intersect().

0

Nếu bạn không hoàn toàn phải sử dụng LINQ, tại sao không viết mã như thế này?

var matches = new List<Template>(); 
    var unmatches = new List<Template>(); 

    foreach (var entry in listForTemplate) 
    { 
     bool matched = false; 
     foreach (var t1Entry in listForTemplate1) 
     { 
      if (entry.ID == t1Entry.ID) 
      { 
       matches.Add(entry); 
       matched = true; 
       break; 
      } 
     } 
     if (!matched) 
     { 
      unmatches.Add(entry); 
     } 
    } 

Một bất lợi của phương pháp LINQ là bạn đang duyệt qua danh sách hai lần.

1

Để so sánh, điều này cũng nên làm việc (phần đầu tiên là một biến thể của câu trả lời @ MAV của):

var matches = from item in listForTemplate 
       join id in listForTemplate1 on item.ID equals id.ID 
       select item; 

var unmatches = listForTemplate.Where(item => matches.All(elem => elem.ID != item.ID)); 

matchesunmatches cả hai sẽ IEnumerable<Template> đó là loại mà bạn yêu cầu.

Tuy nhiên, câu trả lời của MAV hoạt động tốt nên tôi sẽ tìm câu trả lời đó.

Các vấn đề liên quan