使用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", Name = "Test2", 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在上一个列表中而不是当前列表中的情况下显示为"已删除"的项目。

更新

我已经实现了评论中建议的均衡器比较器:

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();
}
}

删除实际上意味着ID已经被删除。

所以听起来你想要列表1中的所有ID,而不是列表2中的ID。

您不需要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));
如果未指定IEqualityComparer<T>,则

.Except()将使用默认的相等比较器。

默认的相等比较器将使用以下逻辑:

  1. 如果类型实现IEquatable<T>,请使用bool Equals(T other)方法
  2. 如果类型覆盖bool Equals(object),请使用该类型
  3. 如果类型是引用类型,请使用ReferenceEquals(object, object)。如果类型是值类型,则会比较该类型中的每个字段

我的猜测是,Data类型是一个不重写任何equals方法的引用类型,因此将使用引用equals。因此,您需要定义对象的比较方式。

如果实现/覆盖任何equals方法,请记住也要覆盖GetHashCode()方法。

相关内容

最新更新