【问题标题】:c# differenciate two lists with objectc# 用对象区分两个列表
【发布时间】:2014-10-30 17:03:45
【问题描述】:

我有这两个列表resultresultNew

data.AddMapping<Employee>(x => x.Name, "Name");
data.AddMapping<Employee>(x => x.Code, "Code");
data.AddMapping<Employee>(x => x.WorkingStatus, "Working Status");
var result = (from x in data.Worksheet<Employee>("Tradesmen")
              select x).ToList();


dataNew.AddMapping<Employee>(x => x.Name, "Name");
dataNew.AddMapping<Employee>(x => x.Code, "Code");
dataNew.AddMapping<Employee>(x => x.WorkingStatus, "Working Status");
var resultNew = (from x in dataNew.Worksheet<Employee>("On Leave")
                 select x).ToList();

其中Employee 是一个简单的c# 代码,其中包含codenameworkingStatus 字段

我想获取coderesultNew 而不是result 的数据

我试过了:

var newEmployees = resultNew.Except(Code = result.Select(s => s.Code)).ToList();

但我遇到了语法错误:

System.Collections.Generic.List' 不包含 'Except' 的定义和最佳扩展方法重载 'System.Linq.Enumerable.Except(System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable )' 有一些无效的参数

【问题讨论】:

  • 如果resultNewList&lt;string&gt; (Codes),那么你可以这样做:resultNew.Except(result.Select(s=&gt; s.Code).ToList(),但这会给你的代码不同。
  • @Habib 不,它在Employee上列出
  • Except 用于处理 2 个枚举。基本上“取这两个相同类型的列表,只返回项目不在另一个列表中的元素”。
  • @TyCobb 但这些是Employee 对象上的列表,我想根据Employy code 进行区分,不是因为有时我们有同名但代码不同的员工。 (代码就像 ID)请教我?
  • 不,我明白了。只是告诉你 Except 实际做了什么以及为什么会出错。

标签: c# linq generics


【解决方案1】:

您可以为新员工的代码创建一个HashSet,然后像这样使用它:

HashSet<string> resultCodes = new HashSet<string>(result.Select(r => r.Code));
List<Employee> newEmployees = resultNew.Where(r => !resultCodes.Contains(r.Code))
                                    .ToList();

您还可以基于属性Code 为您的班级Employee 覆盖EqualsGetHashCode,然后您可以使用Except,例如:

class Employee
{
    protected bool Equals(Employee other)
    {
        return string.Equals(Code, other.Code);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Employee) obj);
    }

    public override int GetHashCode()
    {
        return (Code != null ? Code.GetHashCode() : 0);
    }

    public string Name { get; set; }
    public string Code { get; set; }
    public string WorkingStatus { get; set; }

}

然后:

var newEmployees = resultnew.Except(result).ToList();

记住上面EqualsGetHashCode的实现只考虑Code属性。看到这个问题How do you implement GetHashCode for structure with two string, when both strings are interchangeable

【讨论】:

  • 我打算通过从 resultNew (var resultCodes = resultNew.Select(r =&gt; r.Code);) 中选择代码来使用 IEnumerable&lt;string&gt;。 HashSet 比我的方法性能更好吗?
  • @Brandon,是的。对于较小的数据集,您不会注意到差异。没有HashSet可以做:resultNew.Where(r=&gt; result.Select(s=&gt; s.Code).Contains(r.Code))
  • 在看到您的回答之前,我没有想到 HashSet。感谢您对更大数据集的澄清。很高兴我问了。
  • 感谢您的回答,但也许您误解了我的问题,我想要仅存在于 resultNew 的员工,但您的代码似乎给了我仅存在于 result 的员工请问我对吗?
  • @AnastasieLaurent,覆盖EqualsGetHashCode 并使用Except,您将只获得resultNew 中存在但result 中不存在的那些员工,例如new[] {1, 2, 3,}.Except(new[] {3, 4, 5}).ToList();会给你{1,2}
猜你喜欢
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 2012-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多