第一步 - 为了在
Order
和
OrderItem
类中使用
GroupBy()
,你需要实现
Equals()
和
GetHashCode()
或为这两个类创建一个
EqualityComparer
。请参考
此链接。
在
Order
中重载
Equals()
和
GetHashCode()
(仅基于
Lines
属性):
public class Order
{
public int OrderNumber { get; set; }
public List<OrderLine> Lines { get; set; }
protected bool Equals(Order other)
{
var equals = OrderLinesEquals(Lines, other.Lines);
return equals;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Order) obj);
}
public override int GetHashCode()
{
if (Lines == null)
{
return 0;
}
unchecked
{
int hash = 19;
foreach (OrderLine item in Lines.OrderBy(x => x.Sku, StringComparer.OrdinalIgnoreCase))
{
hash = hash * 31 + item.GetHashCode();
}
return hash;
}
}
private bool OrderLinesEquals(List<OrderLine> x, List<OrderLine> y)
{
if (ReferenceEquals(x, y))
{
return true;
}
if (x == null || y == null)
{
return false;
}
bool areEquivalent = x.Count == y.Count && !x.Except(y).Any();
return areEquivalent;
}
public override string ToString()
{
return $"Sku: {Sku ?? "[null]"}, Quantity: {Quantity}";
}
}
在OrderItem
中覆盖Equals()
和GetHashCode()
方法(基于Sku
和Quantity
属性):
public class OrderLine
{
public string Sku { get; set; }
public int Quantity { get; set; }
protected bool Equals(OrderLine other)
{
return string.Equals(Sku, other.Sku) && Quantity == other.Quantity;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((OrderLine) obj);
}
public override int GetHashCode()
{
unchecked
{
return ((Sku != null ? Sku.GetHashCode() : 0) * 397) ^ Quantity;
}
}
}
测试代码 - 订单列表:
var order1 = new Order
{
OrderNumber = 1,
Lines = new List<OrderLine>
{
new OrderLine
{
Quantity = 10,
Sku = "A"
},
new OrderLine
{
Quantity = 20,
Sku = "B"
}
}
};
var order2 = new Order
{
OrderNumber = 2,
Lines = new List<OrderLine>
{
new OrderLine
{
Quantity = 10,
Sku = "A"
}
}
};
var order3 = new Order
{
OrderNumber = 3,
Lines = new List<OrderLine>
{
new OrderLine
{
Quantity = 20,
Sku = "B"
},
new OrderLine
{
Quantity = 10,
Sku = "A"
}
}
};
var order4 = new Order
{
OrderNumber = 4,
Lines = new List<OrderLine>
{
new OrderLine
{
Quantity = 20,
Sku = "B"
},
new OrderLine
{
Quantity = 10,
Sku = "A"
}
}
};
var order5 = new Order
{
OrderNumber = 5,
Lines = new List<OrderLine>
{
new OrderLine
{
Quantity = 30,
Sku = "C"
}
}
};
var order6 = new Order
{
OrderNumber = 6,
Lines = new List<OrderLine>
{
new OrderLine
{
Quantity = 40,
Sku = "C"
}
}
};
var order7 = new Order
{
OrderNumber = 7,
Lines = new List<OrderLine>
{
new OrderLine
{
Quantity = 30,
Sku = "C"
}
}
};
var orderList = new List<Order>(new[] {order1, order2, order3, order4, order5, order6, order7});
订单分组:
var identicalOrders = orderList.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(g => new
{
Count = g.Count(),
OrderItems = g.Key.Lines,
OrderNumbers = orderList.Where(x => x.Equals(g.Key))
.Select(x => x.OrderNumber)
.ToList()
})
.ToList();
输出: