如何用LINQ从首条记录开始每15分钟提取时序数据?
Got it, let's fix this up. The original grouping logic is using fixed 15-minute markers (like 7:15, 8:15, etc.), which isn't what you need—you want to start from the first record's time and split into 15-minute windows from there.
Here's how to adjust your code and LINQ query to make that happen:
First, let's clean up the original code a bit (that unused data.OrderBy(...) line was just floating there) and implement the window-based grouping correctly:
void ExtractEveryXminute() { List<DataHolder> data = new List<DataHolder>(); Random r = new Random(); DateTime d = new DateTime(2019, 9, 19, 7, 0, 0); // Generate test data for (int i = 0; i < 100; i++) { DataHolder dh = new DataHolder(); TimeSpan t = TimeSpan.FromSeconds(r.Next(0, 14400)); // 0-4 hours of random offset dh.OID = i; dh.Value = r.Next(50); dh.Snapshottime = d.Add(t); data.Add(dh); } // Sort data by timestamp first (critical for window logic) List<DataHolder> sortedList = data.OrderBy(o => o.Snapshottime).ToList(); // Handle empty list case to avoid errors if (!sortedList.Any()) return; // Set our window starting point to the first record's time DateTime firstRecordTime = sortedList.First().Snapshottime; const int windowSizeMinutes = 15; TimeSpan windowDuration = TimeSpan.FromMinutes(windowSizeMinutes); // Group records into 15-minute windows starting from the first record var queryRes = sortedList.GroupBy(record => // Calculate which window this record falls into: // Total minutes from start, divided by window size (integer division gives window index) (int)((record.Snapshottime - firstRecordTime).TotalMinutes / windowSizeMinutes) ) .Select(group => new { // Add readable window bounds for easier use WindowStart = firstRecordTime.AddMinutes(group.Key * windowSizeMinutes), WindowEnd = firstRecordTime.AddMinutes((group.Key + 1) * windowSizeMinutes), RecordsInWindow = group.ToList() }); // Example: Print out the results to verify foreach (var window in queryRes) { Console.WriteLine($"Window: {window.WindowStart:HH:mm:ss} → {window.WindowEnd:HH:mm:ss}"); foreach (var record in window.RecordsInWindow) { Console.WriteLine($" OID: {record.OID}, Value: {record.Value}, Time: {record.Snapshottime:HH:mm:ss}"); } } } public class DataHolder { public int OID { get; set; } public double Value { get; set; } public DateTime Snapshottime { get; set; } }
Key changes explained:
- We use the first record's timestamp as the starting point for all windows, instead of fixed hourly 15-minute markers.
- The group key is calculated using integer division of the time offset from the first record by 15 minutes. This gives us an index for each window (0 = first 15 minutes, 1 = next 15, etc.), so all records in the same 15-minute chunk get grouped together.
- We project each group into an object with clear window start/end times, making it much easier to work with the grouped data later.
This approach ensures your windows align perfectly with your actual data's start time, not arbitrary clock-based markers.
内容的提问来源于stack exchange,提问作者Josef
相关产品推荐
相关产品推荐

