结合List <>,但结合每次比赛的逻辑

时间:2018-10-24 07:19:30

标签: c# .net

我有一个与此非常相似的列表(但示例已简化):

public class TimeEntry
{
    public int entrydate { get; set; } //UNIX Timestamp
    public string name { get; set; }
    public string timespent { get; set; } //Be aware this is a string, not an int or date - [hh]:mm (Hours can go above 24)
}

List<TimeEntry> entryTable = new List<TimeEntry>();


//This layout is fictional and just a representation of my List<TimeEntry>
[entrydate: "1540364988", name: "Time1", timespent: "0:30"],
[entrydate: "1540304400", name: "Time2", timespent: "0:25"],
[entrydate: "1540307400", name: "Time1", timespent: "0:10"],
[entrydate: "1540300010", name: "Time3", timespent: "0:40"],
[entrydate: "1540365000", name: "Time1", timespent: "1:10"],
[entrydate: "1540367500", name: "Time3", timespent: "0:20"],
[entrydate: "1540354500", name: "Time4", timespent: "0:30"]

我想合并每个条目,以便每个唯一的 name 条目每天都有总计。

例如

[entrydate: "1540364988", name: "Time1", timespent: "0:30"],
[entrydate: "1540307400", name: "Time1", timespent: "0:10"],
[entrydate: "1540365000", name: "Time1", timespent: "1:10"]

将成为

[entrydate: "1540252800", name: "Time1", timespent: "0:10"],
[entrydate: "1540339200", name: "Time1", timespent: "1:40"]

我将如何高效地做到这一点?我们正在谈论450,000条记录,我正在考虑仅使用一个循环,但是让一个循环运行450,000次,在每个循环中,我们需要遍历已经存储的所有记录,以查看是否应该计数而不是添加新记录听起来效率低下且缓慢。

不需要完整的代码,但是我很想听听别人对此的看法或解决方案。尽管每一点帮助都值得赞赏 谢谢

编辑:

由于该问题因信息不足而被搁置,因此以下是有关我的问题的更多信息:

目标:合并来自同一且共享相同名称

的每个条目

时间戳记位于 UTC 中,并且一天的时间为 00:00:00到23:59:99。

1 个答案:

答案 0 :(得分:1)

基本上,您需要将entrydate转换为全天值,然后按名称和全天对条目进行分组,然后计算每组的时间。

以下代码完成了所有操作。

  1. 转换entrydateTrimUnixTimestampToDate完成
  2. 分组是使用linq GroupBy函数使用名称和日期的聚合键完成的 通过将每个timespent通过TimeSpan转换为ToTimeSpan并将它们与AddTimespans一起添加来计算时间
    • 请注意,对于格式错误的耗时值,我没有编写适当的错误处理。您必须决定是否需要
  3. 产生的时间跨度转换回字符串
  4. 为汇总数据创建一个新对象

/

List<TimeEntry> TimeEntryProcessing()
{
    var entries = new List<TimeEntry>
    {
        new TimeEntry{ entrydate = 1540364988, name = "Time1", timespent = "0:30"},
        new TimeEntry{ entrydate = 1540304400, name = "Time2", timespent = "0:25"},
        new TimeEntry{ entrydate = 1540307400, name = "Time1", timespent = "0:10"},
        new TimeEntry{ entrydate = 1540300010, name = "Time3", timespent = "0:40"},
        new TimeEntry{ entrydate = 1540365000, name = "Time1", timespent = "1:10"},
        new TimeEntry{ entrydate = 1540367500, name = "Time3", timespent = "0:20"},
        new TimeEntry{ entrydate = 1540354500, name = "Time4", timespent = "0:30"}
    };

    return entries
        .GroupBy(x => new { x.name, date = TrimUnixTimestampToDate(x.entrydate) })
        .Select(x =>
        {
            var time = AddTimespans(x.Select(y => ToTimeSpan(y.timespent)));
            return new TimeEntry
            {
                entrydate = x.Key.date,
                name = x.Key.name,
                timespent = $"{(int)time.TotalHours}:{time.Minutes}"
            };
        })
        // in case you need an order... you didn't mention it
        .OrderBy(x => x.entrydate).ThenBy(x => x.name)
        .ToList();
}

TimeSpan AddTimespans(IEnumerable<TimeSpan> enumerable)
{
    return new TimeSpan(enumerable.Sum(x => x.Ticks));
}

TimeSpan ToTimeSpan(string timespent)
{
    var parts = timespent.Split(':');
    return new TimeSpan(int.Parse(parts[0]), int.Parse(parts[1]), 0);
}

int TrimUnixTimestampToDate(int entrydate)
{
    DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    return (int)dtDateTime.AddSeconds(entrydate).Date.Subtract(dtDateTime).TotalSeconds;
}