获取一个唯一列表<;T>;从三个非唯一列表<;T>';s
本文关键字:列表 gt 唯一 lt 三个 一个 获取 | 更新日期: 2023-09-27 18:21:29
我有三个User
:列表
ICollection<User> listOne = _somewhere.GetUsers(1);
ICollection<User> listTwo = _somewhere.GetUsers(2);
ICollection<User> listThree = _somewhere.GetUsers(3);
要进行比较的"唯一"标识符是一个名为"电子邮件"的字符串字段。
我如何从这三个列表中得到一个唯一的列表(例如,没有重复)。
在使用Except
之前,我从两个列表中获得了一个唯一的列表,但不确定如何使用三个列表?我必须对前两个使用Except
,然后对前两和第三个的结果再次使用吗?
另外,我应该提到用户的列表来自外部Web API调用,并且不能保证每个列表都有一个唯一的电子邮件地址列表。
所以我需要两个步骤:
- 在每个列表中,消除重复
- 将这三个唯一列表组合起来,得到一个唯一列表
您只需联合列表,并在组合列表上执行一次重复数据消除(使用Distinct()
)。
var uniqueList = listOne.Union(listTwo)
.Union(listThree)
.Distinct(new EmailComparer())
.ToList();
因为比较器可以像这样简单:
class EmailComparer : IEqualityComparer<User>
{
public bool Equals(User x, User y)
{
return x.Email == y.Email;
}
public int GetHashCode(User obj)
{
return obj.Email.GetHashCode();
}
}
编辑:
正如评论中所指出的,如果我们将自定义电子邮件比较器应用于Union()
:,则不需要Distinct()
var emailComparer = new EmailComparer();
var uniqueList = listOne.Union(listTwo, emailComparer)
.Union(listThree, emailComparer)
.ToList();
如果从具有相同电子邮件的用户列表中选择哪个用户并不重要,则可以执行以下操作:
var res = listOne.Concat(listTwo).Concat(listThree)
.GroupBy(u => u.Email)
.Select(g => g.First());
同样,这假设当电子邮件地址相同时,选择哪个用户并不重要。
首先定义我们想要如何定义唯一性:
private class EmailEqComparer : IEqualityComparer<User>
{
public bool Equals(User x, User y)
{
//don't bother shortcutting on reference equality, since if they come from
//separate web-calls it's unlikely to happen, though it could
//with some optimisations on the web-client code.
if(x == null)
return y == null;
if(y == null)
return false;
return x.Email == y.Email;
}
public int GetHashCode(User obj)
{
return obj == null ? 0 : obj.Email.GetHashCode();
}
}
现在对每个项目调用Distinct
,并将结果放入一个列表中:
var distinctUnion = listOne.Concat(listTwo).Concat(listThree).Distinct(new EmailEqComparer());