2013-05-11 55 views
5

我有兩個Lists。我想根據ID獲得匹配和不匹配的值,並將結果添加到另一個List。我可以使用Intersect/Except得到這兩個。如何使用c中的Comparsion將List <>複製到另一個List <>

但是我只能得到ID在結果變量(匹配和不匹配)。我需要模板中的所有屬性。

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

回答

3

如果你不想要實現IEquality這個簡單的任務,你可以修改你的LINQ查詢:

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

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

你可能想訪問前檢查null ID,但它應該工作。

+0

我只獲得ID字段(不是全部)匹配和不匹配 我需要所有的屬性。任何幫助! – 2013-05-11 13:06:58

+0

如果你想比較所有的屬性,那麼你將需要實現'IEqualityComparer ' – Ric 2013-05-11 13:13:28

+0

我不想比較所有屬性。只需比較一個屬性(ID)並獲取另一個列表中的所有屬性 – 2013-05-11 13:17:20

2

您正在尋找帶有第二個參數IEqualityComparer的重載函數。因此,讓你的比較器(例如:http://www.blackwasp.co.uk/IEqualityComparer.aspx),並在相交/除外使用相同的比較器。

對於泛型部分:也許你應該有一個模板的通用接口,例如描述該類具有字符串ID屬性的ObjectWithID。或者簡單地在你的比較器中使用動態(但我認爲這是非常非常反模式的,因爲如果使用不好的類型可能會產生運行時錯誤)。

您還有一個問題:將兩個不同類型的集合相交將導致Object(公共父類)的集合。然後你必須施放很多(反模式)。我建議你爲你的模板類創建一個通用的抽象類/接口,並且它正在工作。如果你需要轉換的元素回來,不要投,但使用visitior模式:http://en.wikipedia.org/wiki/Visitor_pattern

示例(良好):

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

輸出:

Matches: 
1 
3 
5 

Ummatches: 
2 
4 
6 

Press any key to continue . . . 
+0

不錯的例子,特別是將它與界面結合在一起。 – Ric 2013-05-11 12:53:22

0

如前所述,落實IEqualityComparer<T>接口。

IEqualityComparer<T> MSDN

然後在你的方法,以此爲論據Except()Intersect()

Intersect

還有就是怎麼做的鏈接Intersect()方法上的一個很好的例子。

0

如果你不一定非要使用LINQ,爲什麼不編寫這樣的代碼?

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

LINQ方法的一個缺點是你遍歷列表兩次。

1

爲了比較,這也應該工作(第一部分是對@ 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)); 

matchesunmatches都將是IEnumerable<Template>這是你需要的類型。

但是,MAV的答案正常,所以我會去那個。

相關問題