【问题标题】:Consolidate a single list of classes合并单个类列表
【发布时间】:2015-01-20 17:22:32
【问题描述】:

我有一个包含事件名称、时间戳和持续时间(时间跨度)的类列表。有许多重复的事件名称。我想按事件名称合并它们并添加它们的持续时间并保留最早的时间戳,除非事件具有特定名称。即,删除重复的事件名称,为类似的事件名​​称添加持续时间,并保留偶数名称中最早的时间戳。

有没有更好的方法来做到这一点?可能与 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);

【问题讨论】:

  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 这绝对可以用 linq 完成,但我并不完全清楚您希望如何聚合这些数据。您能否在帖子中添加一个包含一些示例数据的示例?
  • 感谢约翰桑德斯。我更新了一个示例@pquest。
  • @Jamiec 打败了我。这将工作

标签: c# .net linq list


【解决方案1】:

这一点很简单

我想按事件名称合并它们并添加它们的持续时间并保留最早的时间戳

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&lt;IGrouping&lt;string,eventRecords&gt;&gt;。然后使用Select 投影这些组以构建一个新的eventRecords,并根据要求聚合所需的属性。

现场示例:http://rextester.com/MTVNH46675


在回复您的评论时,您可以在使用Where 对其进行分组之前过滤列表。例如,如果您只想要事件名称长度大于 5 的事件(人为的示例!)

allEventList.Where(e => e.Event.Length>5)
            .GroupBy(e => e.Event)
            .... etc

【讨论】:

  • 有没有办法排除 Event = some key word 的项目?
【解决方案2】:

怎么样:

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 =&gt; entry.TimeStamp) 可以替换为grouping.First().TimeStamp。不知道GroupBy是否保留订单。

【讨论】:

    【解决方案3】:

    我想这就是你所追求的:

     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()
    

    只有一个条目的项目将保持不变

    【讨论】:

      【解决方案4】:

      我使用了 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)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-06
        • 2020-12-03
        • 2018-08-30
        • 1970-01-01
        • 1970-01-01
        • 2019-02-05
        • 2014-03-19
        • 1970-01-01
        相关资源
        最近更新 更多