LINQ查询与Distinct和Union
我目前有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的列表
TheUniqueID = 2,3,4,6,7,9,11,12
换句话说,每个TheUniqueID只出现一次(即2和9不重复)。
我开始关注Union并且很明显,但我想知道我是否需要2个语句。
欢迎任何建议。
我认为frenchie想要一个MyModel列表,而不仅仅是TheUniqueID
。
您需要创建一个MyModelTheUniqueIDComparer
类,并将其作为第二个参数的新实例传递给Union
:
class MyModelTheUniqueIDComparer : IEqualityComparer { 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 { #region IEqualityComparer 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(); var q1 = from a in listOfA select new A() { TheData1 = "TestData", TheData2 = "TestData", UniqueID = a.UniqueID }; var anotherListOfA = new List(); var q2 = from a in anotherListOfA select new A() { TheData1 = "TestData", TheData2 = "TestData", UniqueID = a.UniqueID }; q1.Union(q2, new AComparer());
确保您using System.Linq;
Union
从两个集合中创建一个具有唯一值的Enumerable。 换句话说,你不需要Distinct
。
编辑: 这里的联盟的例子
edit2:忘了它不是你要连接的UniqueIDs
列表。 我删除了建议的代码,因为它错了。 如果实现IEqualityComparer
,你应该能够做一个简单的Union
,但这可能是过度的。
正如所指出的那样,如果.Union(
列表与.Union(
)组合在一起,则必须通过使用为您的类型传递IEqualityComparer的重载来定义唯一性。
var result = q1.Union(q2, myEqualityComparer);
否则,您可以更轻松地使用MoreLinq项目中的DistinctBy( x=> x.TheUniqueId)
:
var result = q1.Concat(q2).DistinctBy(c => c.TheUniqueID);
没有IEqualityComparerer的低效单行答案
使用MoreLinq源代码作为灵感,这将给出一个唯一的列表:
简短回答(OrderBy不是必需的,但如果没有使用,答案就是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 theUniqueIDList1 = new List { 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 theUniqueIDList2 = new List { 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进行速度相比 – 对于IEqualityComparer,对于Concat 100 ns,每个698 ns为10000次