我有两个列表,一个是联系人,另一个是员工。我想生成非员工的联系人子集。以下表达似乎可以告诉我有些联系人不是员工,现在我需要一个符合该标准的联系人列表:
if(myContacts.Select(c=>c.contactID).Except(employees.Select(e=>e.contactID)).Any()
{
//get the subset of contacts and do stuff to them....
}
TIA!
罗恩
答案 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)
如果您的employees
和contacts
序列是同一类型对象(或者两者都来自同一类型,例如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()