4

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

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

蒂亚!

罗恩

4

3 回答 3

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();
于 2012-08-07T15:25:09.800 回答
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();

更新:正如您的评论所示,Contact 和 Employee 是不同的类型,您可以考虑使用 ContactId 属性创建一个接口来创建一个共同的纽带。

或者,我建议将您的 except 结果导出到 a HashSet,然后使用Contains()from the HashSet,这是 O(1) 效率(而不是Contains()在序列上,这是 O(n) 效率):

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

比较使用序列的结果,对于小列表(15 项) Contains()HashSet Contains()您的速度大约快 50%,对于较长的列表甚至更快。

无论如何,只是把它扔在那里,因为序列 ( ) 上的 Contains()IEnumerable<T>相对较慢......

我对这两个解决方案进行了超过 1,000,000 次迭代,并得到:

 HashSet With Contains() took: 1429 ms, 0.001429 ms/item.
 Sequence With Contains() took: 3386 ms, 0.003386 ms/item.
于 2012-08-07T15:34:27.967 回答
1

这不是你要找的吗?

myContacts.Select(c=>c.contactID)
          .Except(employees.Select(e=>e.contactID)
          .ToList()
于 2012-08-07T15:24:01.367 回答