2013-01-16 25 views
5

我有兩個查詢,每個查詢返回一個對象列表。如何合併給定屬性上的兩個列表

List<A> list1 = (....query...) 
List<A> list2 = (....query...) 

「A」是對象模型。

這兩個查詢都返回幾乎相同的對象,但設置了不同的屬性。

我想刪除重複的將它們合併爲基於對象A的屬性

基本上是這樣一個列表:

List<A> finalLis = list1 join list2 on elemList1.somePropID == elemList2.somePropID 

在簡單的C#的風格會是這樣的:

foreach(elem1 : list1) { 
    foreach(elem2: list1) { 
     if(elem1.someID == elem2.someID) { 
      elem1.someProp = elem2.someProp 
      elem1.otherProp = elem2.otherProp 
     } 
    } 
} 

我不想這樣做,因爲我確信linq中有更優雅的方式。

如果您有任何建議,請讓我知道。

+0

你想有從第二收集,不第一個集合中匹配的任何項目ID,在結果集中的項目? – mipe34

+0

否....第一個列表中的元素與第二個列表中的元素幾乎相同。理念是在第一個列表中沒有設置一些屬性,但是這些值可以在對應的對象中找到。最終列表是第一個列表,但所有屬性都設置爲 – cmg

回答

1

的LINQ可以幫助您選擇,但不與更新。所以你不會擺脫foreach聲明。所以,你的任務可能與LINQ這樣寫:

//the query is like LEFT JOIN in SQL 
var query = from x in list1 
      join y in list2 on x.IDItem equals y.IDItem 
      into z 
      from q in z.DefaultIfEmpty() 
      select new {IOne = x, ITwo = q}; 
foreach (var pair in query) 
{ 
    if (pair.ITwo != null) // && pair.IOne.OneProperty != null 
     pair.IOne.OneProperty = pair.ITwo.TwoProperty; 
} 

var resultList = query.Select(x => x.IOne).ToList(); 

您可以檢查結果here

0

試試這個:

List<A> list = (from e1 in list1 
      join e2 in list2 
      on e1.ID equals e2.ID 
      select new A 
      { 
       ID = l2.ID, 
       someProp1 = l2.someProp1, 
       someProp2 = l2.someProp2 
      }).ToList(); 

那麼你將與所有元素的第三個列表。

此鏈接可能幫助:LINQ Join 2 List<T>s

+1

它不包括每個列表中唯一的對象(具有唯一標識)。它也會創建新的對象而不是更新現有的。 –

+0

但他說差異是一些屬性沒有設置爲list1並設置爲list2。而代碼示例的編寫方式我想他想要第三個列表。 –

0

的LINQ是查詢,不更新。您可以簡化連接,但仍然需要循環才能執行更新。

喜歡的東西:

List<A> finalList = 
    from item1 in list1 
    join item2 in list2 on item1.somePropID equals item2.somePropID 
    select new{Item1 = item1, Item2 = item2}; 

foreach(var item in finalList) 
{ 
    item.Item2.someProp1 = item.Item1.someProp1; 
    item.Item2.someProp2 = item.Item1.someProp2; 
} 
+1

同樣的事情 - 最終列表中沒有加入ID。 –

+0

好的我沒有看到解釋的評論。 –

0

想要使用LINQ是正確的。

這裏的答案都等同於給定的C#代碼片段,除此之外片段效率非常低並且會導致list1.Length * list2.Length操作。

使用LINQ連接更加高效,並且大致產生了list1.Length + list2.Length操作。

這是因爲該ID的連接將使用字典

// create a dict so that you can lookup things in item1 based on id 
var list1IdToADict = list1.ToDictionary(a => a.id); 

//filter out things not in both lists (join on there id) 
var joinedList2 = list2.Where(a => list1IdToADict.ContainsKey(a.id)); 

其他答案做這樣的事情更elagant,但如果你想要做這種方式,你可以用

foreach(var a in joinedList2){ 
    a.someProp = list1IdToADict[a.id].someProp; 
    a.otherProp = list1IdToADict[a.id].otherProp; 
} 
完成
0

任何有關List<T>的解決方案都將在N * Log(n)處執行,因爲這些列表需要進行排序。

在您的模型上實現相等成員,並改爲使用HashSet<T>

這在複雜性和分配上都是最佳的。

var set1 = new HashSet<Model> 
{ 
    new Model(0, "000"), 
    new Model(2, "222"), 
    new Model(4, "444"), 
}; 

var set2 = new HashSet<Model> 
{ 
    new Model(1, "111"), 
    new Model(2, "2222"), 
    new Model(3, "333"), 
}; 

set1.ExceptWith(set2); 
set1.UnionWith(set2); 

要添加,使用覆蓋集作爲結果集會更快。

set2.UnionWith(set1); 

Model上述樣本中:

class Model 
{ 
    public readonly int Id; 
    public string Data; 

    public Model(int id, string data) 
    { 
     Id = id; 
     Data = data; 
    } 

    public override int GetHashCode() 
    { 
     return Id; 
    } 

    protected bool Equals(Model other) 
    { 
     return Id == other.Id; 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) return false; 
     if (ReferenceEquals(this, obj)) return true; 
     return obj.GetType() == GetType() && Equals((Model) obj); 
    } 
}