我目前有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个语句。
欢迎任何建议。
答案 0 :(得分:23)
我认为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;
答案 1 :(得分:7)
Union
使用两个集合中的唯一值创建一个Enumerable。换句话说,您不需要Distinct
。
编辑:联盟here
的示例 edit2:忘了它不是你要连接的UniqueIDs
列表。我删除了建议的代码,因为它错了。如果您实施IEqualityComparer
,则应该可以执行简单的Union
,但这可能会有点过分。
答案 2 :(得分:3)
如前所述,如果您将列表与.Union(
组合在一起,则必须使用为您的类型传递IEqualityComparer的重载来定义唯一性。
var result = q1.Union(q2, myEqualityComparer);
否则,您可以更轻松地使用MoreLinq项目中的DistinctBy( x=> x.TheUniqueId)
:
var result = q1.Concat(q2).DistinctBy(c => c.TheUniqueID);
答案 3 :(得分:3)
没有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<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次 Concat为698 ns IEqualityComparer为100 ns