Linq 将两个 ObservableCollection<T> 与 Except 进行比较
Linq compare two ObservableCollection<T> with Except
我已了解 IEqualityComparer
界面。这是我的代码(超过一千字)
static void Main(string[] args)
{
var Send = new ObservableCollection<ProdRow>() {
new ProdRow() { Code = "8718607000065", Quantity = 1 },
new ProdRow() { Code = "8718607000911", Quantity = 10 }
};
var WouldSend = new ObservableCollection<ProdRow>() {
new ProdRow() { Code = "8718607000065", Quantity = 1 },
new ProdRow() { Code = "8718607000072", Quantity = 1 },
new ProdRow() { Code = "8718607000256", Quantity = 1 },
new ProdRow() { Code = "8718607000485", Quantity = 1 },
new ProdRow() { Code = "8718607000737", Quantity = 1 },
new ProdRow() { Code = "8718607000911", Quantity = 20 }
};
//var sendToMuch = Send.Except(WouldSend).ToList();
//var sendToLittle = WouldSend.Except(Send).ToList();
//if (sendToMuch.Any() || sendToLittle.Any())
// var notGood = true;
//else
// var okay = true;
var sendToMuch = Send.ToList();
var sendToLittle = WouldSend.ToList();
foreach (var s in Send) {
var w = WouldSend.FirstOrDefault(d => d.Code.Equals(s.Code));
if (w != null) {
if (w.Quantity == s.Quantity) {
sendToMuch.Remove(s);
sendToLittle.Remove(w);
continue;
}
if (w.Quantity > s.Quantity) {
sendToLittle.Single(l => l.Code == w.Code).Quantity = (w.Quantity - s.Quantity);
sendToMuch.Remove(s);
} else {
sendToMuch.Single(l => l.Code == w.Code).Quantity = (s.Quantity - w.Quantity);
sendToLittle.Remove(s);
}
} else {
sendToMuch.Add(s);
}
}
}
注释行我希望它能起作用...下面的内容是我最终得到的内容。
作为参考,这是我的 ProdRow
class:
class ProdRow : INotifyPropertyChanged, IEqualityComparer<ProdRow>
{
private string _code;
private int _quantity;
public string Code {
get { return _code; }
set {
_code = value;
OnPropertyChanged("Code");
}
}
public int Quantity {
get { return _quantity; }
set {
_quantity = value;
OnPropertyChanged("Quantity");
}
}
private void OnPropertyChanged(string v) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(v));
}
public new bool Equals(object x, object y) {
if (((ProdRow)x).Code.Equals(((ProdRow)y).Code) && ((ProdRow)x).Quantity == ((ProdRow)y).Quantity)
return true;
else
return false;
}
public int GetHashCode(object obj) {
return obj.GetHashCode();
}
public bool Equals(ProdRow x, ProdRow y) {
if (x.Code.Equals(y.Code) && x.Quantity == y.Quantity)
return true;
else
return false;
}
public int GetHashCode(ProdRow obj) {
throw new NotImplementedException();
}
public event PropertyChangedEventHandler PropertyChanged;
}
我没想到评论部分会起作用,因为它不知道要减少数量等的整数,但我想知道是否有比我使用的解决方案更有效的方法来做到这一点(下面注释行)。也许把 collection 压扁成 string[]
?
P.S。对不起 Send
和 WouldSend
的 "PascalCase"
IEqualityComparer<T>
不是为 class 实施的正确接口,您希望比较其 实例 。 IEqualityComparer<T>
实现用于创建从被比较对象的 外部 进行比较的对象,当您需要重新定义两个对象的含义时,这一点变得很重要equal 无需访问这些对象的代码,或者当您需要根据上下文使用不同的语义来实现相等时。
强类型相等比较的正确接口是 IEquatable<T>
。但是,在您的情况下,您只需要覆盖 Object
的 Equals(object)
和 GetHashCode()
:
public new bool Equals(object obj) {
if (obj == this) return true;
var other = obj as ProdRow;
if (other == null) return false;
return Code.Equals(other.Code) && Quantity == other.Quantity;
}
public int GetHashCode() {
return 31*Code.GetHashCode() + Quantity;
}
就计算量而言,你可以用负数来计算,GroupBy
:
var quantityByCode = WouldSend.Select(p => new {p.Code, p.Quantity})
.Concat(Send.Select(p => new {p.Code, Quantity = -p.Quantity}))
.GroupBy(p => p.Code)
.ToDictionary(g => g.Key, g => g.Sum(p => p.Quantity));
var tooLittle = quantityByCode
.Where(p => p.Value > 0)
.Select(p => new ProdRow {Code = p.Key, Quantity = p.Value})
.ToList();
var tooMuch = quantityByCode
.Where(p => p.Value < 0)
.Select(p => new ProdRow {Code = p.Key, Quantity = -p.Value})
.ToList();
我已了解 IEqualityComparer
界面。这是我的代码(超过一千字)
static void Main(string[] args)
{
var Send = new ObservableCollection<ProdRow>() {
new ProdRow() { Code = "8718607000065", Quantity = 1 },
new ProdRow() { Code = "8718607000911", Quantity = 10 }
};
var WouldSend = new ObservableCollection<ProdRow>() {
new ProdRow() { Code = "8718607000065", Quantity = 1 },
new ProdRow() { Code = "8718607000072", Quantity = 1 },
new ProdRow() { Code = "8718607000256", Quantity = 1 },
new ProdRow() { Code = "8718607000485", Quantity = 1 },
new ProdRow() { Code = "8718607000737", Quantity = 1 },
new ProdRow() { Code = "8718607000911", Quantity = 20 }
};
//var sendToMuch = Send.Except(WouldSend).ToList();
//var sendToLittle = WouldSend.Except(Send).ToList();
//if (sendToMuch.Any() || sendToLittle.Any())
// var notGood = true;
//else
// var okay = true;
var sendToMuch = Send.ToList();
var sendToLittle = WouldSend.ToList();
foreach (var s in Send) {
var w = WouldSend.FirstOrDefault(d => d.Code.Equals(s.Code));
if (w != null) {
if (w.Quantity == s.Quantity) {
sendToMuch.Remove(s);
sendToLittle.Remove(w);
continue;
}
if (w.Quantity > s.Quantity) {
sendToLittle.Single(l => l.Code == w.Code).Quantity = (w.Quantity - s.Quantity);
sendToMuch.Remove(s);
} else {
sendToMuch.Single(l => l.Code == w.Code).Quantity = (s.Quantity - w.Quantity);
sendToLittle.Remove(s);
}
} else {
sendToMuch.Add(s);
}
}
}
注释行我希望它能起作用...下面的内容是我最终得到的内容。
作为参考,这是我的 ProdRow
class:
class ProdRow : INotifyPropertyChanged, IEqualityComparer<ProdRow>
{
private string _code;
private int _quantity;
public string Code {
get { return _code; }
set {
_code = value;
OnPropertyChanged("Code");
}
}
public int Quantity {
get { return _quantity; }
set {
_quantity = value;
OnPropertyChanged("Quantity");
}
}
private void OnPropertyChanged(string v) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(v));
}
public new bool Equals(object x, object y) {
if (((ProdRow)x).Code.Equals(((ProdRow)y).Code) && ((ProdRow)x).Quantity == ((ProdRow)y).Quantity)
return true;
else
return false;
}
public int GetHashCode(object obj) {
return obj.GetHashCode();
}
public bool Equals(ProdRow x, ProdRow y) {
if (x.Code.Equals(y.Code) && x.Quantity == y.Quantity)
return true;
else
return false;
}
public int GetHashCode(ProdRow obj) {
throw new NotImplementedException();
}
public event PropertyChangedEventHandler PropertyChanged;
}
我没想到评论部分会起作用,因为它不知道要减少数量等的整数,但我想知道是否有比我使用的解决方案更有效的方法来做到这一点(下面注释行)。也许把 collection 压扁成 string[]
?
P.S。对不起 Send
和 WouldSend
IEqualityComparer<T>
不是为 class 实施的正确接口,您希望比较其 实例 。 IEqualityComparer<T>
实现用于创建从被比较对象的 外部 进行比较的对象,当您需要重新定义两个对象的含义时,这一点变得很重要equal 无需访问这些对象的代码,或者当您需要根据上下文使用不同的语义来实现相等时。
强类型相等比较的正确接口是 IEquatable<T>
。但是,在您的情况下,您只需要覆盖 Object
的 Equals(object)
和 GetHashCode()
:
public new bool Equals(object obj) {
if (obj == this) return true;
var other = obj as ProdRow;
if (other == null) return false;
return Code.Equals(other.Code) && Quantity == other.Quantity;
}
public int GetHashCode() {
return 31*Code.GetHashCode() + Quantity;
}
就计算量而言,你可以用负数来计算,GroupBy
:
var quantityByCode = WouldSend.Select(p => new {p.Code, p.Quantity})
.Concat(Send.Select(p => new {p.Code, Quantity = -p.Quantity}))
.GroupBy(p => p.Code)
.ToDictionary(g => g.Key, g => g.Sum(p => p.Quantity));
var tooLittle = quantityByCode
.Where(p => p.Value > 0)
.Select(p => new ProdRow {Code = p.Key, Quantity = p.Value})
.ToList();
var tooMuch = quantityByCode
.Where(p => p.Value < 0)
.Select(p => new ProdRow {Code = p.Key, Quantity = -p.Value})
.ToList();