如何解决使用Linq Except返回从列表中删除但具有相同ID
我有以下列表:
var previousRun = new List<Data>();
var currentRun = new List<Data>();
var item1= new Data() { Id = "1",Address = "Test Address",Name = "Test",PostCode = "ABC DEF" };
var item2 = new Data() { Id = "2",Address = "Test Address2",Name = "Test2",PostCode = "GHI JKL" };
var item1Updated = new Data() { Id = "1",Address = "UpdatedAddress",Name = "UpdatedTest",PostCode = "STU VWX" };
var item2Updated= new Data() { Id = "2",Address = "UpdatedAddress2",PostCode = "TES TIN" };
previousRun.Add(item1);
previousRun.Add(item2);
currentRun.Add(item1updated);
currentRun.Add(item2updated);
我正在计算从当前列表中的上一个列表中删除的项目数:
public DataChange<Data>[] Compare(Data[] previous,Data[] current)
{
var deletedResults = previous
.Except(current)
.Select(DataChange<Data>.Deleted)
.ToList();
}
在这种情况下,我希望结果为0,因为没有删除任何内容,仅对其进行了更新(我很欣赏可以说原始文档已被“删除”,但我还会列出更新的项目,因此删除确实意味着ID已被删除。
相反,deletedResults
是2,因为它认为两个原始项目都已被删除。任何人都可以通过Linq查询提供帮助,如果ID在上一个列表中,而不是当前列表中,则仅将项目显示为“已删除”。
更新
我已按照评论中的建议实施了一个EqualityComparer:
public class DataEqualityComparer: IEqualityComparer<GpLookupData>
{
public bool Equals(Data previous,Data current)
{
var idComparer = string.Equals(previous.Id,current.Id,System.StringComparison.OrdinalIgnoreCase);
var nameComparer = string.Equals(previous.Name,current.Name,System.StringComparison.OrdinalIgnoreCase);
var addressComparer = string.Equals(previous.Address,current.Address,System.StringComparison.OrdinalIgnoreCase);
var postcodeComparer = string.Equals(previous.PostCode,current.PostCode,System.StringComparison.OrdinalIgnoreCase);
if (idComparer && nameComparer && addressComparer && postcodeComparer)
{
return true;
}
return false;
}
public int GetHashCode(Data obj)
{
return obj.Name.GetHashCode();
}
}
解决方法
如果未指定
.Except()
, IEqualityComparer<T>
将使用默认的相等比较器。
默认的相等比较器将使用以下逻辑:
- 如果该类型实现了
IEquatable<T>
,请使用bool Equals(T other)
方法 - 如果类型覆盖
bool Equals(object)
,请使用该类型。 - 如果类型是引用类型,请使用
ReferenceEquals(object,object)
。如果类型是值类型,则将比较类型中的每个字段。
我的猜测是,数据类型是不覆盖任何equals方法的引用类型,因此将使用引用相等。因此,您需要定义如何比较对象。
如果您实现/覆盖任何equals方法,请记住也要覆盖GetHashCode()
方法。
删除实际上意味着ID已被删除。
所以听起来您想要列表1中的所有ID,但列表2中没有。
您不需要Except
和一个相等比较器-只需:
var deleted = previousRun.Where(p => !currentRun.Any(c => c.Id == p.Id));
如果您需要更好的性能,则可以从“当前” ID创建哈希集:
var idList = new HashSet<int>(currentRun.Select(c => C.Id));
var deleted = previousRun.Where(p => idList.Contains(p.Id));
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。