Lambda表达式可以对比不同的对象

时间:2012-08-07 15:18:45

标签: c# .net lambda

我有两个列表,一个是联系人,另一个是员工。我想生成非员工的联系人子集。以下表达似乎可以告诉我有些联系人不是员工,现在我需要一个符合该标准的联系人列表:

if(myContacts.Select(c=>c.contactID).Except(employees.Select(e=>e.contactID)).Any()
{
   //get the subset of contacts and do stuff to them....
}

TIA!

罗恩

3 个答案:

答案 0 :(得分:3)

 var nonEmployees = contacts.Where(w=> ! employees.Any(e=>e.contactID == w.contactID)).ToList();

 var nonEmployees = contacts.Where(w=> ! employees.Select(s=>s.contactID).Contains(w.contactID) ).ToList();

答案 1 :(得分:2)

如果您的employeescontacts序列是同一类型对象(或者两者都来自同一类型,例如Contact),那么您可以创建一个EqualityComparer实例:

public class ContactComparer : EqualityComparer<Contact>
{
    public override bool Equals(Contact x, Contact y)
    {
        if (ReferenceEquals(x, y)) return true;

        return x != null && y != null && x.ContactId == y.ContactId;
    }

    public override int GetHashCode(Contact obj)
    {
        if (obj == null) throw new ArgumentNullException("obj");

        // assuming string
        return (obj.ContactId ?? "").GetHashCode();
    }
}

这可以让你这样做,因此你可以直接返回结果而不必双重查询:

var contactsNotEmployees = myContacts.Except(employees, new ContactComparer()).ToList();

更新:如您的注释所示,联系人和员工是不同的类型,您可以考虑使用ContactId属性创建一个界面来创建公共债券。

或者,我建议将您的除外结果导出到HashSet,然后使用Contains()中的HashSet,这是效率为O(1)(而不是{{1}在一个序列上,这是O(n)效率):

Contains()

比较使用序列 // get hash set of contact-only IDs var except = new HashSet<int>(contacts .Select(c => c.ContactId) .Except(emplopyees.Select(e => e.ContactId))); // get the objects for those IDs var others = contacts.Where(c => except.Contains(c.ContactId)).ToList(); Contains() HashSet的结果,对于小型列表(15项),您的速度提高约50%,对于较长的列表,速度会更快。

无论如何,只是抛出那个,因为序列(Contains())上的Contains()相对较慢......

我为两个解决方案计时超过1,000,000次迭代并获得:

IEnumerable<T>

答案 2 :(得分:1)

这不是你想要的吗?

myContacts.Select(c=>c.contactID)
          .Except(employees.Select(e=>e.contactID)
          .ToList()