从三个非唯一List <t> </t> </t>中获取一个唯一的List <t>

时间:2012-01-27 00:00:32

标签: c# .net linq

我有三个User列表:

ICollection<User> listOne = _somewhere.GetUsers(1);
ICollection<User> listTwo = _somewhere.GetUsers(2);
ICollection<User> listThree = _somewhere.GetUsers(3);

要比较的“唯一”标识符是名为“电子邮件”的字符串字段。

如何从三个中获得一个唯一的列表(例如没有欺骗)。

在使用Except之前,我有一个来自两个列表的唯一列表,但不确定如何使用三个?我是否必须在前两个使用Except,然后在前两个和第三个的结果上再次使用它?

另外,我应该提及用户列表来自外部Web API调用,并且无法保证每个列表都有唯一的电子邮件地址列表。

所以我需要两个步骤:

  1. 在每个清单中,摆脱欺骗
  2. 合并三个唯一列表以获得一个唯一列表。

3 个答案:

答案 0 :(得分:4)

您可以在列表中合并列表并执行重复数据删除(使用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();
    }
}

修改:

如果我们将自定义电子邮件比较器应用于Distinct(),则不需要在评论Union()中指出:

var emailComparer = new EmailComparer();
var uniqueList = listOne.Union(listTwo, emailComparer)
                        .Union(listThree, emailComparer)
                        .ToList();

答案 1 :(得分:3)

如果您从具有相同电子邮件的用户列表中选择哪个用户并不重要,您可以这样做:

var res = listOne.Concat(listTwo).Concat(listThree)
    .GroupBy(u => u.Email)
    .Select(g => g.First());

同样,这假设当电子邮件地址相同时,您选择的用户无关紧要。

答案 2 :(得分:2)

首先定义我们如何定义唯一性:

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