通过id区分对象列表

时间:2013-12-18 10:35:06

标签: c# asp.net list linq-to-sql distinct

我有一个程序,其中有一个主题(如论坛),人们可以对该主题做出反应。

USER:

  1. ID
  2. 名字
  3. 姓氏
  4. TOPIC:

    1. ID
    2. 受试者
    3. 反应:

      1. ID
      2. topic_id
      3. 含量
      4. 代码:

        List<USER> ListOfAllUsers = new List<USER>();
        var AllReactions = from r in db.REACTIONs
                           where r.topic_id == _topic_id
                           select r;
        
        foreach (var itemX in AllReactions)
        {
            ListOfAllUsers.Add(itemX.USER);
        }
        
        //Distinct the list of duplicates
        var ListOfUsers = ListOfAllUsers.Distinct().ToList();
        

        现在,“distinct”列表仍然有一些重复,如何根据用户ID区分列表?或者也许有另一种更好的方法来做到这一点。提前谢谢。

5 个答案:

答案 0 :(得分:17)

您可以使用GroupBy来实现

var ListOfUsers = ListOfAllUsers.GroupBy(x => x.Id)
                                  .Select(g => g.First())
                                  .ToList();

答案 1 :(得分:3)

我建议您让数据库为您返回不同的用户:

    List<USER> ListOfAllUsers = 
         db.REACTIONs.Where(r => r.topic_id == _topic_id)
                     .Select(r => r.USER)
                     .Distinct()
                     .ToList();

这将被翻译成单个SQL查询。类似的东西(假设你的USER表有两列--Id和Name):

SELECT 
    [Distinct1].[Id] AS [Id], 
    [Distinct1].[Name] AS [Name]
    FROM ( SELECT DISTINCT 
        [Extent2].[Id] AS [Id], 
        [Extent2].[Name] AS [Name]
        FROM  [dbo].[USER] AS [Extent1]
        INNER JOIN [dbo].[REACTION] AS [Extent2] 
            ON [Extent1].[Id] = [Extent2].[UserId]
        WHERE @id = [Extent1].[topic_id]
    )  AS [Distinct1]

答案 2 :(得分:2)

Distinct有一个重载,它接收IEqualityComparer<T>的实例,该实例包含允许LINQ知道哪两个对象相等的逻辑,因此应该删除一个。

你需要实现这个(非常简单的)接口,如下所示:

public class UserEqualityComparer : IEqualityComparer<User>
{
      public bool Equals(User x, User y)
      {
           return x.Id == y.Id;
      }

      public int GetHashCode (User obj)
      {
           return obj.Id.GetHashCode();
      }
}

然后将UserEqualityComparer的实例传递给Distinct()

var ListOfUsers = ListOfAllUsers.Distinct(new UserEqualityComparer()).ToList();

答案 3 :(得分:1)

MoreLinq(在NuGet上可用)有一个DistincBy方法,允许您将委托用作相等比较器。

所以你只需做这样的事情:

var ListOfUsers = ListOfAllUsers.DistinctBy(user => user.id).ToList();

修改:MoreLinq Link

答案 4 :(得分:0)

我在 .Net core 中尝试过类似的代码。无需定义显式比较器。 在类中覆盖 EqualsGetHashcode。 无需GroupBy。默认情况下,即使其他 props 不同,Distinct() 也能工作。

public class User  
    {
        public int Id { get; set; }    
        public string FirstName { get; set; }            
        public string LastName { get; set; }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(this, obj)) return true;    
            if (obj is User && (obj as User).Id == this.Id) return true;    
            return false;          
        }

        public override int GetHashCode()
        {
            int hashProductCode = Id.GetHashCode();    
            return hashProductCode;
        }    
    }

User[] users =  {
                new User {Id=1, FirstName="John", LastName="Smith" },
                new User {Id=2, FirstName="Mary", LastName="Blood" },
                new User {Id=1, FirstName="Sergey", LastName="Ivanov" }
            };

            var usersDistinct = users.Distinct().ToArray();
            Console.WriteLine(usersDistinct.Count()); //2 =John + Mary