首页 > 解决方案 > 使用 Linq 除了返回从列表中删除但具有相同 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,因为它认为两个原始项目都已被删除。如果 Id 在上一个列表中但不在当前列表中,任何人都可以请帮助进行 Linq 查询,该查询只会将项目显示为“已删除”。

更新

我已经按照评论中的建议实施了 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();
        }
    }

标签: c#linq

解决方案


.Except()IEqualityComparer<T>如果 a未指定,将使用默认的相等比较器。

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

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

我的猜测是 Data-type 是一个引用类型,它不会覆盖任何 equals 方法,因此将使用引用相等。因此,您需要定义对象的比较方式。

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


推荐阅读