合并单个类列表

时间:2015-01-20 17:22:32

标签: c# .net linq list

我有一个类列表,其中包含事件名称,时间戳和持续时间(时间跨度)。有许多重复的事件名称。我想通过事件名称对它们进行合并,并添加它们的持续时间并保留最早的时间戳,除非事件具有某个名称。即,删除重复的事件名称,添加类似事件名称的持续时间,并保留偶数名称的最早时间戳。

有更好的方法吗?可能还有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);

4 个答案:

答案 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)
}