2013-05-11 11 views
5

I o posiadaniu dwóch Lists. Chcę uzyskać dopasowane i niedopasowane wartości oparte na ID i dodać wyniki do innego List. Mogę uzyskać oba z nich za pomocą Intersect/Except.Jak skopiować listę <> do innej listy <> za pomocą narzędzia Comparsion C#

Ale mogę uzyskać tylko ID w wynikowych zmiennych (dopasowań i zniekształceń). Potrzebuję wszystkich właściwości w szablonie.

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; } 
    } 

Odpowiedz

3

Jeśli nie chcą wprowadzić IEquality dla tego prostego zadania, można po prostu zmodyfikować zapytań LINQ:

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

i

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

Możesz chcieć sprawdzić dla wartości null przed dostępem ID, ale powinno działać.

+0

Otrzymuję tylko pole identyfikacyjne (nie wszystkie) dla zapałek i wypustek Potrzebuję wszystkich właściwości. Pomocy! –

+0

Jeśli chcesz porównać ze wszystkimi właściwościami, musisz zaimplementować "IEqualityComparer " – Ric

+0

Nie chcę porównywać ze wszystkimi właściwościami. Wystarczy porównać z jedną właściwością (ID) i uzyskać wszystkie właściwości z innej listy. –

2

Szukacie przeciążonej funkcji, z drugim parametrem IEqualityComparer. Stwórz więc swojego porównywalnika (przykład: http://www.blackwasp.co.uk/IEqualityComparer.aspx) i użyj tego samego porównania na przecięciu/z wyjątkiem.

Część ogólna: może powinieneś mieć wspólny interfejs dla szablonów, np. ObjectWithID opisujące, że klasa ma właściwość String ID. Lub po prostu użyj dynamicznego w twoim kontrolerze (ale myślę, że to jest bardzo-bardzo antypodstawowe ponieważ możesz mieć błędy czasu pracy jeśli używasz dla złego typu).

Masz również problem: przecięcie dwóch kolekcji z dwoma różnymi typami spowoduje powstanie kolekcji Object (wspólnej klasy nadrzędnej). Następnie musisz dużo rzucać (antypatia). Radzę utworzyć wspólną klasę/interfejs dla klas szablonów i działa. Jeśli trzeba rzucić elementy z powrotem, nie rzucać, ale użyć wzoru visitior: http://en.wikipedia.org/wiki/Visitor_pattern

Przykład (dobrze):

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; } 
} 

wyjściowa:

Matches: 
1 
3 
5 

Ummatches: 
2 
4 
6 

Press any key to continue . . . 
+0

Dobry przykład, zwłaszcza połączenie go z interfejsem. – Ric

0

Jak wspomniano, wdrożenie Interfejs IEqualityComparer<T>.

IEqualityComparer<T> MSDN

Następnie użyć tego jako argumentu w swoim sposobie Except() i Intersect()

Intersect

Nie jest dobrym przykładem, jak to zrobić odnośnik do metody Intersect().

0

Jeśli nie musisz koniecznie używać LINQ, czemu nie napisać czegoś takiego?

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); 
     } 
    } 

Wadą podejścia LINQ jest to, że dwukrotnie przeglądasz listy.

1

Dla porównania, to powinno również pracować (pierwsza część to wariacja na odpowiedź @ Mav):

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)); 

matches i unmatches będą zarówno być IEnumerable<Template>, która jest typem potrzebują.

Jednak odpowiedź MAV działa dobrze, więc wybrałbym tę.

Powiązane problemy