我有一个类列表,其中包含事件名称,时间戳和持续时间(时间跨度)。有许多重复的事件名称。我想通过事件名称对它们进行合并,并添加它们的持续时间并保留最早的时间戳,除非事件具有某个名称。即,删除重复的事件名称,添加类似事件名称的持续时间,并保留偶数名称的最早时间戳。
有更好的方法吗?可能还有Linq?
这是我尝试过的,似乎没有正确合并(仍然有重复但却少了)
班级:
public class eventRecords
{
public DateTime TimeStamp { get; set; }
public string Event { get; set; }
public TimeSpan Duration { get; set; }
}
我的尝试:
// allEventList is already sorted by TimeStamp, so my thinking is adding
// the first occurrence of an event to newList will keep the earliest
// TimeStamp in eventRecrods for that event
// Also - the duplicates are almost all consecutive in allEventList
var newList = new List<eventRecords>();
for (int ii = 0; ii < allEventList.Count; ii++ )
{
newList.Add(allEventList[ii]);
if((ii + 1) < allEventList.Count && allEventList[ii] != keyword)
{
if(allEventList[ii].Event == allEventList[ii+1].Event)
{
newList.Last().Duration = newList.Last().Duration+ allEventList[ii + 1].Duration;
ii = ii + 1;
}
}
}
例如,如果allEventList包含:
Event = "Action 1", TimeStamp = 08:00, Duration = TimeSpan.FromMinutes(1);
Event = "Action 1", TimeStamp = 09:00, Duration = TimeSpan.FromMinutes(1);
Event = "Action 1", TimeStamp = 10:00, Duration = TimeSpan.FromMinutes(1);
Event = "KeyWord", TimeStamp = 11:00, Duration = TimeSpan.FromMinutes(1);
Event = "Action 2", TimeStamp = 12:00, Duration = TimeSpan.FromMinutes(1);
Event = "Action 2", TimeStamp = 13:00, Duration = TimeSpan.FromMinutes(1);
newList应包含:
Event = "Action 1", TimeStamp = 08:00, Duration = TimeSpan.FromMinutes(3);
Event = "KeyWord", TimeStamp = 11:00, Duration = TimeSpan.FromMinutes(1);
Event = "Action 2", TimeStamp = 12:00, Duration = TimeSpan.FromMinutes(2);
答案 0 :(得分:9)
这一点相当容易
我想按事件名称合并它们并添加其持续时间并保留最早的时间戳
allEventList.GroupBy(e => e.Event)
.Select(g => new eventRecords{
TimeStamp = g.Min(e => e.TimeStamp),
Event = g.Key,
Duration = new TimeSpan(g.Sum(e => e.Duration.Ticks))
});
这首先按Event
对您的列表进行分组,然后为您提供IEnumerable<IGrouping<string,eventRecords>>
。然后使用Select
投影这些群组以构建新的eventRecords
,并根据要求汇总所需的素材。
实例:http://rextester.com/MTVNH46675
在回答您的评论时,您可以在使用Where
对其进行分组之前对列表进行过滤。例如,如果您只想要事件名称长度大于5的事件(设想示例!)
allEventList.Where(e => e.Event.Length>5)
.GroupBy(e => e.Event)
.... etc
答案 1 :(得分:3)
怎么样:
allEventList
.GroupBy(x => x.Event)
.Select(grouping => new eventRecords
{
Event = grouping.Key,
TimeStamp = grouping.Min(entry => entry.TimeStamp),
Duration = new TimeSpan(grouping.Sum(entry => entry.Duration.Ticks))
};
可能grouping.Min(entry => entry.TimeStamp)
可以替换为grouping.First().TimeStamp
。我不知道GroupBy
是否保留了订单。
答案 2 :(得分:1)
我认为这就是你所追求的:
var list = new List<EventRecords>();
list.Add(new EventRecords{ TimeStamp = new DateTime(2014,1,1), Event = "1", Duration = new TimeSpan(1)});
list.Add(new EventRecords { TimeStamp = new DateTime(2013, 1, 1), Event = "1", Duration = new TimeSpan(1) });
list.Add(new EventRecords { TimeStamp = new DateTime(2014, 1, 1), Event = "2", Duration = new TimeSpan(1) });
list.Add(new EventRecords { TimeStamp = new DateTime(2012, 1, 1), Event = "3", Duration = new TimeSpan(1) });
var output = list.GroupBy(e => e.Event)
.Select(e => new EventRecords
{
Event = e.Key,
Duration = new TimeSpan(e.Sum(ee => ee.Duration.Ticks)),
TimeStamp = e.Select(ee => ee.TimeStamp).Min()
});
对于具有相同事件名称的项目,请将它们的时间长度相加:
new TimeSpan(e.Sum(ee => ee.Duration.Ticks)),
//create a new timespan from the sum of all timespan ticks
并抓住他们最早的时间戳:
e.Select(ee => ee.TimeStamp).Min()
只有一个条目的项目将保持不变
答案 3 :(得分:0)
我使用了Northwind数据库,但这似乎可以做你想要的:
from o in Orders
where o.CustomerID != "HANAR"
group o by o.CustomerID into ox
select new
{
Event = ox.Key,
Start = ox.Min (o => o.OrderDate),
Duration = ox.Sum(o=>o.Freight)
}