我正在尝试从单元测试开始编写一个 linq 语句,该语句从一天中的一个小时开始按天对考试进行分组。
基本条件如下
1st exam with recording date 2024-03-21T11:20:00, Id = 3;
2nd exam with recording date 2024-03-21T11:50:00, Id = 4;
3rd exam with recording date 2024-03-21T12:20:00, Id = 5;
4th exam with recording date 2024-03-21T12:50:00, Id = 6;
5th exam with recording date 2024-03-22T11:20:00, Id = 7;
6th exam with recording date 2024-03-22T11:50:00, Id = 8;
7th exam with recording date 2024-03-22T12:20:00, Id = 9;
8th exam with recording date 2024-03-23T12:50:00, Id = 10;
9th exam with recording date 2024-03-23T11:20:00, Id = 11;
10th exam with recording date 2024-03-23T11:50:00, Id = 12;
11th exam with recording date 2024-03-23T12:20:00, Id = 13;
12th exam with recording date 2024-03-23T12:50:00, Id = 24;
如果按从中午开始的一天进行分组,则要达到的结果如下
1st visit with Id = 1 and exams with Id = [3, 4]
2nd visit with Id = 5 and exams with Id = [5, 6, 7, 8]
3rd visit with Id = 9 and exams with Id = [9, 10, 11, 12]
4th visit with Id = 13 and exams with Id = [13, 24]
或者如果按从中午开始的几天分组
1st visit with Id = 1 and exams with Id = [3, 4]
2nd visit with Id = 5 and exams with Id = [5, 6, 7, 8, 9, 10, 11, 12]
3rd visit with Id = 13 and exams with Id = [13, 24]
这是第一个测试简单条件的单元测试
[TestMethod]
public void Convert_TwoExamSplitAtNoon_TwoVisits()
{
PatientWithExams p = new() { PatientId = 1 };
p.Exams.Add(new LightExam()
{
ExamId = 1,
ExamType = Micromed.Domain.Archive.Types.ExamFileTypeId.EegTrace,
RecordingDate = new DateTime(2024, 3, 21, 11, 20, 00)
});
p.Exams.Add(new LightExam()
{
ExamId = 1,
ExamType = Micromed.Domain.Archive.Types.ExamFileTypeId.EegTrace,
RecordingDate = new DateTime(2024, 3, 21, 12, 20, 00)
});
List<PatientWithExams> patients = new() { p };
TimeSpan splitTime = new(12, 00, 00);
Dictionary<int, List<LightVisit>> visits = _converter.ConvertNew(patients, splitTime);
// Assert
Assert.AreEqual(true, visits[1].Count() == 2);
}
我能够编写将考试转换为访问的方法,但实际上我不考虑按小时休息
TimeSpan groupInterval = TimeSpan.FromDays(1);
var eegExams = from e in patient.Exams.Where(e => e.ExamType == Domain.Archive.Types.ExamFileTypeId.EegTrace)
group e by e.RecordingDate.Ticks / groupInterval.Ticks into g
select new { day = new DateTime(g.Key * groupInterval.Ticks), Values = g.Count(), Exams = g.DefaultIfEmpty() };
谢谢, 瑞克
您尝试做的是某种分箱或加窗,通常用于创建直方图。您有一个起点和所需的时间段或窗口长度(例如 1 天)。然后迭代所有元素并生成 bin/window id 并按此 id 对元素进行分组。这是一个代码示例,您可以根据需要采用:
public class Program
{
static void Main(string[] args)
{
var now = DateTime.UtcNow;
var items = Enumerable.Range(1, 10)
.Select(i => new Item { Id = i, Occurence = now.AddHours(i * 5) })
.ToList();
var twelveHourWindows = items
.GroupBy(item => GetWindow(item.Occurence, now));
foreach (var group in twelveHourWindows)
{
Console.WriteLine($"Group id: {group.Key}");
foreach (var item in group)
{
Console.WriteLine($" {item.Id} {item.Occurence}");
}
}
}
private static DateTime GetWindow(DateTime occurence, DateTime start)
{
var diff = occurence - start;
var steps = (int)Math.Floor(diff.TotalHours / 12);
return start.AddHours(steps * 12);
}
}
public class Item
{
public int Id { get; set; }
public DateTime Occurence { get; set; }
}
神奇的东西发生在
GetWindow()
方法内。该方法从当前项获取起始点和相应的值来计算所需的窗口 id 并返回窗口的值,该值应该用于该项。
希望这可以帮助您解决您的问题。