【问题标题】:LINQ merging two Lists and grouping by timestampsLINQ合并两个列表并按时间戳分组
【发布时间】:2013-01-26 18:51:18
【问题描述】:

早上好,我需要将两个列表合并在一起并从中创建一个数据表,我有以下代码块:

private static DataTable GetDataTable(IList<DataValue> listOneDataValues,
                                            IList<DataValue> listTwoDataValues)
      {
         var dataTable = new DataTable();
         dataTable.Columns.Add("ColumnFromListOne");
         dataTable.Columns.Add("ColumnFromListTwo");
         dataTable.Columns.Add("TimeStamp");

         //Group the lists together
         var query = (from listOne in listOneDataValues
                      from listTwo in listTwoDataValues
                      let columnFromListOne= listOne.DoubleValue
                      let columnFromListTwo= listTwo.DoubleValue
                      let timestamp = listOne.TimeStamp
                      where listOne.TimeStamp == listTwo.TimeStamp
                      select new {ColumnFromListTwo = columnFromListOne, ColumnFromListOne = columnFromListTwo, Timestamp = timestamp});


         foreach(var q in query)
            dataTable.Rows.Add(q.ColumnFromListOne, q.ColumnFromListTwo, q.TimeStamp);

         return dataTable;
      }

问题是这两个列表包含的时间戳相差几秒钟,而且它们根本不对齐,所以我的最终结果是数据表中的一条或零条记录,即使每个列表都包含 200 + 记录。我对 LINQ 很不满意,希望能在正确的方向上有所帮助。我想我需要在分组之前插入时间戳,但我想知道执行此类操作的最佳实践模式。

【问题讨论】:

  • 您想如何处理相差几秒钟的时间戳?它们不同的,所以它们应该被视为不同的。您可以四舍五入或截断到最近的分钟,但如果时间戳跨越那条线怎么办?你可以找到它们之间的距离,但如果你有很多事件,你会得到重叠。
  • 最低粒度级别是每 5 分钟一次。我需要四舍五入到我猜的最接近的 5 分钟。

标签: c# asp.net linq


【解决方案1】:

您可以将 where 语句更改为

where Math.Abs((listOne.TimeStamp - listTwo.TimeStamp).TotalSeconds) &lt; 5

这会将两次相差 5 秒的时间视为“相同”

【讨论】:

  • 我会避免这里的幻数。创建一个 epsilon 或阈值变量,并确保根据数据进行一些测试以确定合适的值是多少。差异也可能以毫秒为单位,而不是秒。
【解决方案2】:

您需要确定将两个时间戳称为“相等”的适当阈值 - 知道阈值太大会导致误报,阈值太小会阻止某些记录加入。

从那里只需将您的查询更改为

     int threshold = 5;
     //Group the lists together
     var query = (from listOne in listOneDataValues
                  from listTwo in listTwoDataValues
                  where Math.Abs(
                                    (listOne.TimeStamp - listTwo.TimeStamp)
                                     .TotalSeconds
                                ) <= threshold
                  select new {
                                 ColumnFromListTwo = listTwo.DoubleValue,
                                 ColumnFromListOne = listOne.DoubleValue, 
                                 Timestamp = listOne.TimeStamp
                             });

【讨论】:

  • 这两个都是很好的答案,不过为了完整起见。
猜你喜欢
  • 1970-01-01
  • 2018-11-10
  • 1970-01-01
  • 2017-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多