Linq - 如何按'let'值进行分组并将另一个'let'值相加

时间:2015-10-19 10:50:42

标签: c# linq

我正在使用一个我无法控制的API,它将来自SQL服务器的数据作为List<string>返回,并且每个字符串的列都以逗号分隔。

此特定数据集以varchardatetime的形式返回,如下所示:

{
    "Prefix_IdentifierA,1/1/1900 12:30:00 AM,", 
    "Prefix_IdentifierA,1/1/1900 12:15:00 AM,", 
    "Prefix_IdentifierB,1/1/1900 01:00:00 AM,", 
    "Prefix_IdentifierB,1/1/1900 12:45:00 AM,"
}

datetime仅代表时间,因此所有日期都相同。

我需要将其转换为具有每个标识符的总持续时间的对象集合:

public class Log
{
    public string Identifier { get; set; }

    public int DurationInSeconds { get; set; }
}

因此,生成的集合应如下所示:

{
    Log { Identifier = "IdentifierA", DurationInSeconds = 45 },
    Log { Identifier = "IdentifierB", DurationInSeconds = 105 }
}

目前我在2个Linq查询中执行此操作:

1)从每一行中提取IdentifierDurationInSeconds

var logs1 = (from row in rows
             select row.Split(',')
             into columns
             let identifier = columns[0].Replace("Prefix_", string.Empty)
             let duration = DateTime.Parse(columns[1])
             let durationInSeconds = duration.Hour * 3600 + duration.Minute * 60 + duration.Second
             select new { Identifier = identifier, DurationInSeconds = durationInSeconds }).ToList();

2)按Identifier和总和DurationInSeconds进行分组:

var logs2 = (from log in logs1
             group log by log.Identifier
             into grouping
             orderby grouping.Key
             select new Log { Identifier = grouping.Key, DurationInSeconds = grouping.Sum(log => log.DurationInSeconds) }).ToList();

第一个查询中的匿名类型与Log对象相同,那么有没有办法将这两个查询合并为一个?

编辑:到目前为止我的进展

我已经按identifier进行分组,但无法确定如何获得durationInSeconds的总和:

var logs = (from row in rows
            select row.Split(',')
            into columns
            let identifier = columns[0].Replace("Prefix_", string.Empty)
            let duration = DateTime.Parse(columns[1])
            let durationInSeconds = duration.Hour * 3600 + duration.Minute * 60 + duration.Second
            group rows by identifier
            into grouping
            select new { Identifier = grouping.Key, DurationInSeconds = grouping.Sum(?????) }).ToList();

2 个答案:

答案 0 :(得分:4)

您可以按identifier分组,返回IGrouping<IEnumarable<T>>,这样您就可以从中获取标识符,这只是Key,然后您可以再次投影IEnumarable为每个标识符提供并在其中解析duration变量。请注意,在对数据进行分组之前无需存储它。

此查询应该可以正常使用: -

var logs =  (from row in rows
            select row.Split(',') into columns
            let identifier = columns[0].Replace("Prefix_", string.Empty)
            group columns by identifier into g
            select new Log { 
                  Identifier = g.Key, 
                  DurationInSeconds = (from dur in g
                                      let duration = DateTime.Parse(dur[1])
                                      select duration.Hour * 3600 + duration.Minute * 60 
                                              + duration.Second).Sum()
                           }).ToList();

答案 1 :(得分:2)

如何将查询语法与方法语法相结合?

(...)select new { Identifier = identifier, DurationInSeconds = durationInSeconds }).GroupBy(l => l.Identifier)(...)