2011-03-11 77 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