You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:44:19