c# Linq通过组合键int, list分组
本文关键字:int list 分组 Linq 组合 | 更新日期: 2023-09-27 18:14:01
我有一个产品对象,它具有该产品的特定位置和允许的运输方法。我想做的是按位置和允许的运输方式对产品进行分组。
例如,下面的示例数据将产生两个分组,一个是IDLocation = 1, ShipMethods为1,2,计数为2,另一个是IDLocation = 1, ShipMethods为1,2,计数为3。
public class CartProduct
{
public int IDLocation { get; set; }
public List<int> ShipMethods { get; set; }
public List<CartProduct> GetExampleData()
{
return new List<CartProduct>() { new CartProduct() { IDLocation = 1, ShipMethods = new List<int>(){ 1, 2 } },
new CartProduct() { IDLocation = 1, ShipMethods = new List<int>(){ 1, 2 } },
new CartProduct() { IDLocation = 1, ShipMethods = new List<int>(){ 3, 4 } },
new CartProduct() { IDLocation = 1, ShipMethods = new List<int>(){ 3, 4 } },
new CartProduct() { IDLocation = 1, ShipMethods = new List<int>(){ 3, 4 } }
};
}
}
我希望首先看到IDLocation的分组,然后如果船舶方法是相同的组那些在一起。
我尝试了几个版本的分组,并选择了许多没有运气。
List<CartProduct> CPList = new CartProduct().GetExampleData();
var GroupItems = CPList.GroupBy(x => x.IDLocation) // then by ShipMethods??
我认为关键是使用GroupBy的能力来指定分组时使用的"键"。你想把具有相同IDLocation和相同ShipMethods集合的东西分组在一起,所以键应该包括那些东西。理想情况下,你应该使用一个正确的比较器来做正确的事情。做这件事的一种简单的方法(更容易写,所以我可以肯定这是可行的)是把所有的东西混在一起成一个字符串,这样普通的字符串比较就能完成我们想要的。下面是简单的答案:
var answer = GetExampleData()
.GroupBy(x=>String.Format("{0} {1}",
x.IDLocation,
String.Join(",",x.ShipMethods.OrderBy(y=>y))));
为了获得更好的性能,您必须实现我所描述的"适当"方式。这是一点工作,但它不应该太难。
edit:我正在对ShipMethods进行排序,以便可以通过1或2发送的东西被正确地视为与可以通过2或1发送的东西相同。理想情况下,ShipMethods列表已经排序,这样可以节省时间。
(时髦的格式是试图使它不滚动而可见)
GroupBy
中的comparer
参数允许您为对象分组的目的定义相等性。比较器是一个单独的类,它比较两个相似的对象,如果它们相等,则返回true
。需要实现IComparer<CartItem>
的类可以这样实现:
class CartGroupComparer : IEqualityComparer<CartProduct>
{
public bool Equals(CartProduct x, CartProduct y)
{
return x.IDLocation == y.IDLocation
&& x.ShipMethods.OrderBy(x=>x)
.SequenceEqual(y.ShipMethods.OrderBy(x=>x));
}
public int GetHashCode(CartProduct obj)
{
return obj.IDLocation.GetHashCode()
^ obj.ShipMethods.Sum().GetHashCode();
}
}
(注意:为了简单起见,这里假设ShipMethods
永远不会为空)
Equals
方法测试两个项目是否相等;如果相等,它们将被添加到同一组。GetHashCode
方法必须对相等的项返回相等的值,上面有一个简单的实现。
你可以直接在GroupBy
子句中使用这个比较器:
new CartProduct().GetExampleData()
.GroupBy(a => a, new CartGroupComparer());