我有这堂课:
public class Change()
{
public int Id {get; set;}
public decimal Price {get; set;}
}
我有2个列表oldPrices
和newPrices
。两个列表包含相同的项目,但不同的实例。
newPrices
中的某些项目有不同的价格,所以要获取我正在做的更改价格列表:
var list = newPrices
.Where(x => oldPrices.All(p => p.Price != x.Price))
.ToDictionary(x => x.Id, x => x.Price);
这个表达式应该是正确的,但即使有变化,列表也是空的。
我错过了什么?
答案 0 :(得分:2)
Enumerable.All
返回true。那不是你想要检查的。您希望获得与旧价格不同的所有新价格。
您必须先Id
加入两个列表才能比较价格:
var joined = from np in newPrices
join op in oldPrices
on np.Id equals op.Id
where np.Price != op.Price
select np;
var newPricesById = joined.ToDictionary(p => p.Id, p => p.Price);
答案 1 :(得分:1)
All
检查oldPrices
中所有元素的条件是否为真。我想你想要的是检查具有相同ID的项目的价格是否已经改变。
我建议先将旧列表转换为字典:
var oldPricesDic = oldPrices.ToDictionary(x => x.Id, x => x.Price);
然后像这样过滤新列表:
var list = newPrices
.Where(x => !oldPricesDic.ContainsKey(x.Id) ||
oldPricesDic[x.Id] != x.Price)
.ToDictionary(x => x.Id, x => x.Price);
现在返回包含所有已更改(或新)项目的字典。
答案 2 :(得分:1)
你可以让Change class IEquatable<Change>
允许一个简单的LINQ except()调用:
void Main()
{
var oldPrices = new List<Change> {
new Change { Id = 1, Price = 1.5M },
new Change { Id = 2, Price = 5.0M }
};
var newPrices = new List<Change> {
new Change { Id = 1, Price = 1.5M },
new Change { Id = 2, Price = 5.75M }
};
var list = newPrices.Except(oldPrices).ToDictionary(x => x.Id, x => x.Price);
}
public class Change : IEquatable<Change>
{
public int Id {get; set;}
public decimal Price {get; set;}
public bool Equals(Change other)
{
if (Object.ReferenceEquals(other, null)) return false;
if (Object.ReferenceEquals(this, other)) return true;
return Id.Equals(other.Id) && Price.Equals(other.Price);
}
public override int GetHashCode()
{
int hashId = Id.GetHashCode();
int hashPrice = Price.GetHashCode();
return hashId ^ hashPrice;
}
}
答案 3 :(得分:0)
您也可以尝试这2个左外连接解决方案..
var pricesFromLeftJoin =
(from np in newPrices
join op in oldPrices on np.Id equals op.Id into subOldPrices
from subPrice in subOldPrice.DefaultIfEmpty()
where subPrice == null || (subPrice != null && subPrice .Price != np.Price)
select np).ToDictionary(x => x.Id, x => x.Price);
var pricesFromLeftJoin_compactForm =
(from np in newPrices
from op in oldPrices.Where(op => (op.Id == np.Id)).DefaultIfEmpty()
where op == null || (op != null && op.Price != np.Price)
select np).ToDictionary(x => x.Id, x => x.Price);
答案 4 :(得分:0)
正如其他人指出All
要求序列的所有元素都满足条件。它也可以使用Enumerable.Zip
方法完成:
var dictionary = newPrices.OrderBy(c => c.Id)
.Zip(oldPrices.OrderBy(p => p.Id), (c, p) => p.Price != c.Price ? c : null)
.Where(c => c != null).ToDictionary(c => c.Id, c => c.Price);