【问题标题】:Linq distinct - CountLinq distinct - 计数
【发布时间】:2011-06-20 13:06:04
【问题描述】:

我希望对示例对象列表执行查询

Date     Username

01/01/2011 james
01/01/2011 jamie
01/01/2011 alex
01/01/2011 james
02/01/2011 matt
02/01/2011 jamie
02/01/2011 alex
02/01/2011 james
02/01/2011 james
02/01/2011 lucy
02/01/2011 alex
03/01/2011 james
03/01/2011 bob
03/01/2011 bob
03/01/2011 james
03/01/2011 james
04/01/2011 alex
04/01/2011 alex
04/01/2011 alex

我想使用 linq 来查询日期列表以及唯一用户登录的次数。

例如:

01/01/2011 - 3
02/01/2011 - 5
03/01/2011 - 2
04/01/2011 - 1

我已经尝试了许多 linq 语句,但这些语句都没有给我想要的结果。我得到的最接近的是给我不同的日期,但对所有用户进行计数。

任何帮助将不胜感激。

【问题讨论】:

  • 请添加您尝试过的那些 LINQ 语句 - 然后我们可以看到它们出错的原因。

标签: c# linq


【解决方案1】:
logins
  .GroupBy(l => l.Date)
  .Select(g => new
  {
    Date = g.Key,
    Count = g.Select(l => l.Login).Distinct().Count()
  });

【讨论】:

  • 我是 Linq 新手,我想知道您将如何用 Linq 查询语法而不是 Linq 方法语法来编写它。
  • @comecme 我知道你很久以前就留下了这条评论,但请查看我对下面方法语法的翻译。
  • 恐怕您的代码将始终返回 Count=1,那是因为您添加了 Disctinct() 并将计数一个元素。如果删除它,您将拥有元素的数量。希望这可以帮助!!! ;)
  • 例如,对于某些源数组 [1, 1, 2]:distinct count = 2, count = 3。显然,它们中没有一个不等于 1。我们确实需要 distinct如果我们需要计算唯一登录。仅使用 Count 会给出错误的数字(登录总数,不是唯一的)。
  • 如果没有区别,它会给出该日期的总登录会话数。即使它们是针对同一用户的。使用 distinct - 它给出每个日期登录的用户数。可能,您的主题启动器的数据结构/目标编号略有不同
【解决方案2】:

可能是这样的吗?

var list = new List<MyClass>(new[] {
        new MyClass { Date = DateTime.Parse("01/01/2011"), Username = "james" },
        new MyClass { Date = DateTime.Parse("01/01/2011"), Username = "james" },
        new MyClass { Date = DateTime.Parse("01/01/2011"), Username = "alex" },
        new MyClass { Date = DateTime.Parse("01/01/2011"), Username = "james" },
        new MyClass { Date = DateTime.Parse("02/01/2011"), Username = "matt" },
        new MyClass { Date = DateTime.Parse("02/01/2011"), Username = "jamie" },
        new MyClass { Date = DateTime.Parse("02/01/2011"), Username = "alex" },
        new MyClass { Date = DateTime.Parse("02/01/2011"), Username = "james" },
        new MyClass { Date = DateTime.Parse("02/01/2011"), Username = "james" },
        new MyClass { Date = DateTime.Parse("02/01/2011"), Username = "lucy" },
        new MyClass { Date = DateTime.Parse("02/01/2011"), Username = "alex" },
        new MyClass { Date = DateTime.Parse("03/01/2011"), Username = "james" },
        new MyClass { Date = DateTime.Parse("03/01/2011"), Username = "bob" },
        new MyClass { Date = DateTime.Parse("03/01/2011"), Username = "bob" },
        new MyClass { Date = DateTime.Parse("03/01/2011"), Username = "james" },
        new MyClass { Date = DateTime.Parse("03/01/2011"), Username = "james" },
        new MyClass { Date = DateTime.Parse("04/01/2011"), Username = "alex" },
        new MyClass { Date = DateTime.Parse("04/01/2011"), Username = "alex" },
        new MyClass { Date = DateTime.Parse("04/01/2011"), Username = "alex" }
    });

list.GroupBy(l => l.Date, l => l.Username)
    .Select(g => new { 
                Date = g.Key, 
                Count = g.Distinct().Count() 
            });

【讨论】:

  • 啊,我太接近了,谢谢你,我会尽快考虑实施。感谢您的快速回复。
  • @aspect - 实际上,这会为您提供具有相关唯一用户登录次数的日期,从您的问题来看,您是否也想将具有相同数量的唯一用户登录的日期分组?如果这就是您想要的,那么只需在按计数选择后添加另一个分组,您就可以了!
  • 这似乎是我们最好的解决方案!最初我分组了两次,但我真的不喜欢这样做。这在 SQL 中非常简单,但在 LINQ 中最好的方法并不那么明显。为了每个人的利益:如果您要将日期编写为代码中的字符串,则应使用 ISO 格式。这样可以确保解释不依赖于语言环境。
【解决方案3】:

解决这个问题的另一种方法是分组两次,检查样本

          var dist = listLogins.GroupBy(d => d.date + d.Username)
              .Select(x => x.First())
              .GroupBy(d => d.date).Select(y => new { date = y.Key, count = y.Count() }).ToList();

【讨论】:

    【解决方案4】:

    可以在单个 GroupBy 调用中完成,

      var Query = list.GroupBy(
                     (item => item.DateTime),
                     (key, elements) => new  { 
                                              key = key,
                                              count = elements
                                                      .Distinct()
                                                      .Count()
                                             }
                     );
    

    【讨论】:

    • 这是最好的答案。谢谢@naveen
    • 它会给出错误的结果(每天的总会话数,而不是每天唯一的用户名)
    【解决方案5】:

    我意识到这是一个古老的问题,但我遇到了它,看到了关于想要方法语法的评论,无法帮助自己回答......我可能有编码障碍。

    在查询语法中,它看起来像这样...请注意,DistinctCount 没有查询语法

    from l in logins
    group l by l.Date into g
    select new
    {
        Date = g.Key,
        Count = (from l in g select l.Login).Distinct().Count() 
    };
    

    这里是与原始方法语法(我个人更喜欢)的并排比较...

    logins
      .GroupBy(l => l.Date)
      .Select(g => new
      {
        Date = g.Key,
        Count = g.Select(l => l.Login).Distinct().Count()
      });
    

    【讨论】:

    • 感谢您抽出宝贵时间回答我的评论。
    【解决方案6】:

    我认为 Oryol 的答案不需要区分计数。 groupup 自动选择不同的键,它可以作为 g.key 访问

    logins
      .GroupBy(l => l.Date)
      .Select(g => new
      {
        Date = g.Key,
        Count = g.Select(l => l.Login).Count()
      });
    

    【讨论】:

    • 我看不出这会奏效。您的代码仅按日期分组,而不是按登录名。如果没有 Distinct,它肯定会计算每天的登录总数,而不是每天登录的不同用户数?
    猜你喜欢
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 2011-06-29
    • 2012-11-15
    • 1970-01-01
    相关资源
    最近更新 更多