C# Linq查询按分组并汇总到新列表中

C# Linq查询按分组并汇总到新列表中,c#,linq,C#,Linq,所以我在尝试构造一个查询时遇到了一个小噩梦,尽管它真的不应该那么困难 我要去上课 public class visitItem { public int visitId {get; set;} public int contactId {get; set;} public int locationId {get; set;} public DateTime FirstSeen {get; set;} public DateTime LastSeen {ge

所以我在尝试构造一个查询时遇到了一个小噩梦,尽管它真的不应该那么困难

我要去上课

public class visitItem
{
    public int visitId {get; set;}
    public int contactId {get; set;}
    public int locationId {get; set;}
    public DateTime FirstSeen {get; set;}
    public DateTime LastSeen {get; set;}
    public double Duration {get; set;}
}
基本上,我有一个json中的访问历史日期,我将它反序列化为
visitItem
列表,并从数据中形成几个不同的图表

我想做的是从主列表中创建一个新列表,在主列表中我选择了一个特定的月份,结果列表现在按contactId分组,持续时间汇总如下:

List<visitItem> totalDurations = visits
  .Where(x => x.FirstSeen.ToString("MM") == month)......
而不是:

contactId          duration
1                  5
1                  5 
2                  5
3                  5
4                  10
4                  10

如何实现这一点?

您需要按月筛选,然后根据联系人id对项目进行分组,然后对这些组的持续时间求和。例如,五月:

var month = 5;

var durationByContact = from visit in visits
                        where visit.FirstSeen.Month == month
                        group visit by visit.contactId
                        into visitsByContact
                        select new
                        {
                            ContactId = visitsByContact.Key,
                            TotalDuration = visitsByContact.Sum(i => i.Duration)
                        };
或在方法语法中:

var durationByContact = visits
    .Where(v => v.FirstSeen.Month == month)
    .GroupBy(v => v.contactId)
    .Select(g => new
    {
        ContactId = g.Key,
        TotalDuration = g.Sum(i => i.Duration)
    });

为什么要执行字符串转换?当然,使用
FirstSeen.Month
会更简单。。。无论如何,您还没有解释为什么需要第一个输出,或者输入是什么。。。现在你刚刚说你希望它是X而不是Y,这给了我们很少的上下文来帮助你…啊-在重新格式化这个问题之后,它更有意义。在发布问题之前,请注意预览问题,以确保它确实有意义。接下来,您说您已按contactId分组,但您根本没有显示查询的这一部分,这再次使您很难提供帮助。理想情况下,提供一个简短但完整的程序来演示这个问题……很抱歉,原始帖子中的格式错误。我现在只是回头看了看,我想我已经构建了我的答案,就像上面的编辑文章一样。我并不是想说我是按contactId分组的,我的意思是,我首先只选择x月的访问,就可以得到一个相关的列表。然后,应该对结果列表进行分组和汇总等。感谢您的帮助否,它按月份筛选,按联系人ID分组。@JonSkeet您是对的-问题编辑解释得更好,我不确定以前是否清楚。我已经更新了。谢谢你的回复。这正是我想要的。我只是将其编辑为
Select(g=>newvisititem{ContactId=g.Key,Duration=g.Sum(I=>I.Duration})
,以便于在foreach循环中使用并避免匿名类型的列表。作为一个附加查询,我如何在查询的Select部分包括FirstSeen?例如
.Select(g=>newvisititem){ContactId=g.Key,TotalDuration=g.Sum(i=>i.Duration),FirstSeen=?});
FirstSeen的值是多少?因为您只根据
ContactId
进行分组,所以
FirstSeen
可以在该组中有不同的值(尽管所有值都在
month
中,因为您已经根据该值进行了筛选)。
var durationByContact = visits
    .Where(v => v.FirstSeen.Month == month)
    .GroupBy(v => v.contactId)
    .Select(g => new
    {
        ContactId = g.Key,
        TotalDuration = g.Sum(i => i.Duration)
    });