2011-03-11 91 views
13

LINQ查詢我公司目前有2個查詢將要返回爲MyModel的名單如下:具有獨特和聯盟

var q1 = .... 
     select new MyModel() 
     { 
      TheData1 = ... 
      TheData2 = ... 
      TheUniqueID = ... 
     } 

var q2 = .... 
     select new MyModel() 
     { 
      TheData1 = ... 
      TheData2 = ... 
      TheUniqueID = ... 
     } 

如果在Q1我有:

TheUniqueID = 2,3,6,9,11 

,並在Q2我有:

TheUniqueID = 2,4,7,9,12 

怎麼做才能讓我得到爲MyModel的一個列表,其中

編寫查詢0
TheUniqueID = 2,3,4,6,7,9,11,12 

換句話說,每個TheUniqueID只出現一次(即。 2和9沒有重複)。

我開始看着聯盟和不同,但我想知道如果我需要2從聲明或不。

歡迎任何建議。

+0

開發這是LINQ到對象或LINQ to SQL的等? – 2011-03-11 17:30:39

+0

這是一個SQL查詢語句 – frenchie 2011-03-14 03:18:43

回答

21

我認爲frenchie想要一份MyModel的清單,而不僅僅是TheUniqueID

你需要創建一個MyModelTheUniqueIDComparer類,並通過它的一個新的實例作爲第二個參數爲Union

class MyModelTheUniqueIDComparer : IEqualityComparer<MyModel> 
{ 
    public bool Equals(MyModel x, MyModel y) 
    { 
     return x.TheUniqueID == y.TheUniqueID; 
    } 

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects. 

    public int GetHashCode(MyModel myModel) 
    { 
     return myModel.TheUniqueID.GetHashCode(); 
    } 
} 

然後你可以打電話得到的結果:

var result = q1.Union(q2, new MyModelTheUniqueIDComparer()); 

http://msdn.microsoft.com/en-us/library/bb358407.aspx瞭解更多細節。

更新:

試試這個:

public class A 
{ 
    public string TheData1 { get; set; } 
    public string TheData2 { get; set; } 
    public string UniqueID { get; set; } 
} 

public class AComparer : IEqualityComparer<A> 
{ 

    #region IEqualityComparer<A> Members 

    public bool Equals(A x, A y) 
    { 
     return x.UniqueID == y.UniqueID; 
    } 

    public int GetHashCode(A obj) 
    { 
     return obj.UniqueID.GetHashCode(); 
    } 

    #endregion 
} 

和測試這一點:

var listOfA = new List<A>(); 
var q1 = from a in listOfA 
       select new A() 
      { 
       TheData1 = "TestData", 
       TheData2 = "TestData", 
       UniqueID = a.UniqueID 
      }; 

var anotherListOfA = new List<A>(); 
var q2 = from a in anotherListOfA 
       select new A() 
       { 
        TheData1 = "TestData", 
        TheData2 = "TestData", 
        UniqueID = a.UniqueID 
       }; 

q1.Union(q2, new AComparer()); 

請確保您有using System.Linq;

+0

啊!我知道這不會是一件簡單的事情!我正在休息一下,我會回來嘗試一下。謝謝你的幫助。 – frenchie 2011-03-11 17:55:01

+0

我收到用於查詢運算符聯合錯誤的不受支持的重載。我試圖投但它不工作:返回結果作爲列表或返回(列表)結果不適用於返回語句。任何想法爲什麼? – frenchie 2011-03-11 19:13:56

+0

try 'return q1.Union(q2,new MyModelTheUniqueIDComparer())。ToList();' – 2011-03-11 19:25:20

3

正如您指出的那樣,如果您將列表與.Union(組合在一起),您將不得不通過使用通過IEqualityComparer類型的重載來定義唯一性。

var result = q1.Union(q2, myEqualityComparer); 

否則,而且更容易,你可以使用DistinctBy(x=> x.TheUniqueId)MoreLinq項目:

var result = q1.Concat(q2).DistinctBy(c => c.TheUniqueID); 
+0

MoreLinq似乎已經成爲一個死鏈接。試試這個:https://code.google.com/p/morelinq/ – 2014-12-07 06:51:15

6

Union創建一個可枚舉來自兩個集合的唯一值。換句話說,你不需要Distinct

編輯:例如聯盟here

EDIT2的:忘記了它不是UniqueIDs,你串聯列表。由於錯誤,我刪除了建議的代碼。如果你實施了IEqualityComparer,你應該可以做一個簡單的Union,但這可能是矯枉過正。

3

低效單行ANS WER沒有IEqualityComparerer

使用MoreLinq源代碼爲靈感,這將給唯一列表:

簡答題(的排序依據是沒有必要的,但如果不使用答案出來爲2,3,6 ,9,11,4,7,12):

var concattedUniqueList = theUniqueIDList1.Concat(theUniqueIDList2) 
      .GroupBy(f=>f.UniqueID, f=>f).Select(g => g.First()).OrderBy(f=>f.UniqueID); 

完整回答:

//INPUT 
//theUniqueIDList1 = 2,3,6,9,11 
//theUniqueIDList2 = 2,4,7,9,12 
//OUTPUT 
//2,3,4,6,7,9,11,12 
public class MyModel 
{ 
    public string TheData1 { get; set; } 
    public string TheData2 { get; set; } 
    public int UniqueID { get; set; } 
} 

public static void GroupByEx1() 
    { 
     // Create a list of Models. 
     List<MyModel> theUniqueIDList1 = 
      new List<MyModel>{ new MyModel { TheData1="Barley", UniqueID=2 }, 
            new MyModel { TheData1="Boots",  UniqueID=3 }, 
            new MyModel { TheData1="Whiskers", UniqueID=6 }, 
            new MyModel { TheData1="Daisy",  UniqueID=9 }, 
            new MyModel { TheData1="Preti",  UniqueID=11 } }; 
     List<MyModel> theUniqueIDList2 = 
      new List<MyModel>{ new MyModel { TheData1="Barley", UniqueID=2 }, 
            new MyModel { TheData1="Henry",  UniqueID=4 }, 
            new MyModel { TheData1="Walsh",  UniqueID=7 }, 
            new MyModel { TheData1="Daisy",  UniqueID=9 }, 
            new MyModel { TheData1="Ugly", UniqueID=12 } }; 

     var concattedUniqueList = theUniqueIDList1.Concat(theUniqueIDList2) 
      .OrderBy(f=>f.UniqueID).GroupBy(f=>f.UniqueID, f=>f).Select(g => g.First()); 

     foreach (var item in concattedUniqueList) 
     { 
      Console.WriteLine("UniqueId: {0}({1})", item.UniqueID, item.TheData1); 
     } 
    } 

void Main() 
{ 
    GroupByEx1();    
    //2,3,4,6,7,9,11,12 
} 

注:相對於使用的IEqualityComparer速度 - 10000次每個 698納秒爲的毗連 100納秒爲的IEqualityComparer

LinqPad

+1

在我看來這是最好的答案。這比製作自己的比較器要好得多。要做模糊我會做'.GroupBy(f => f.UniqueID,f => f).SelectMany(g => g.Take(1));'作爲習慣性地不調用'的方法.First()' 。它在這裏工作,但在調用'.First()'的其他查詢中可能會導致問題。但肯定仍然是最好的答案。 – Enigmativity 2014-12-16 04:11:37

+0

如果兩個列表具有不同的類型,但參數UniqueID在兩個列表中都相同,該怎麼辦? – 2016-03-23 13:39:35