3

我有一个产品对象,该对象具有特定的位置和该产品允许的运输方式。我要做的是按位置和允许的运输方式对产品进行分组。

例如,下面的示例数据将生成两个分组,其中一个 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 ,然后如果船舶方法是同一组,那么它们也在一起。

我已经尝试了几个版本的 group by 并选择了很多没有运气。

List<CartProduct> CPList = new CartProduct().GetExampleData();
var GroupItems  = CPList.GroupBy(x => x.IDLocation) // then by ShipMethods??
4

2 回答 2

2

我认为关键是利用 GroupBy 的能力来指定分组时使用的“键”。您希望将具有相同 IDLocation 和同一组 ShipMethods 的事物组合在一起,因此键应包含这些事物。理想情况下,您会使用正确的比较器来做正确的事情。执行此操作的 hackish 方法(更容易编写,因此我可以告诉这会起作用)是将所有内容混合成一个字符串,以便正常的字符串比较可以满足我们的要求。所以这里是快速的答案:

var answer = GetExampleData()
             .GroupBy(x=>String.Format("{0} {1}",
                         x.IDLocation,
                         String.Join(",",x.ShipMethods.OrderBy(y=>y))));

为了获得更好的性能,您必须实现我所描述的“正确”方式。这有点工作,但不应该太难。

编辑:我正在对 ShipMethods 进行排序,以便可以正确地看到可以通过 1 或 2 运送的东西与可以通过 2 或 1 运送的东西相同。理想情况下,ShipMethods 列表已经排序,因此我们可以节省时间.

(时髦的格式是尝试使其在不滚动的情况下可见)

于 2013-05-15T23:03:18.910 回答
1

comparerin 参数GroupBy允许您为对象分组定义相等性。比较器是一个单独的类,它比较两个相似的对象,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());
于 2013-05-15T23:28:11.477 回答