Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ query with Distinct and Union

Tags:

I currently have 2 queries that are returning lists of MyModel like this:

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

If in q1 I have:

TheUniqueID = 2,3,6,9,11  

and in q2 I have:

TheUniqueID = 2,4,7,9,12 

How do write the query so that I get a list of MyModel where

TheUniqueID = 2,3,4,6,7,9,11,12 

In other words, each TheUniqueID is present only once (ie. 2 and 9 not repeated).

I started looking at Union and distinct but I'm wondering if I need 2 from statements or not.

Any suggestions are welcome.

like image 888
frenchie Avatar asked Mar 11 '11 17:03

frenchie


2 Answers

I think frenchie wants a list of MyModel back instead of just the TheUniqueID.

You need to create a MyModelTheUniqueIDComparer class and pass a new instance of it as a second argument into 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();     } } 

Then you can call to get the result:

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

See http://msdn.microsoft.com/en-us/library/bb358407.aspx for a more details.

Update:

Try this:

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 } 

And test with this:

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

Make sure you have using System.Linq;

like image 90
Thomas Li Avatar answered Nov 07 '22 21:11

Thomas Li


Union creates an Enumerable with unique values from both collections. In other words, you don't need Distinct.

edit: example of Union here

edit2: forgot that it's not the list of UniqueIDs that you're concatenating. I removed the suggested code since it was wrong. You should be able to do a simple Union if you implement an IEqualityComparer, but that might be overkill.

like image 24
vlad Avatar answered Nov 07 '22 23:11

vlad