我有以下代码
TimeSpan[] hours = new[] {
new TimeSpan(10,35,50),
new TimeSpan(10,36,48),
new TimeSpan(10,41,48),
new TimeSpan(10,47,58),
new TimeSpan(10,49,14),
new TimeSpan(11,22,15),
new TimeSpan(11,24,18),
new TimeSpan(11,25,25),
};
我想将小时和分钟按5分钟分组。 我想得到下面的结果
第一小组
**10:35:50
10:36:48
10:41:48**
第二组
**10:47:58
10:49:14**
第三小组
**11:22:15
11:24:18
11:25:25**
我尝试了以下代码,但无法获得所需的确切结果
var query = (from x in hours select x)
.GroupBy(r=> r.Ticks / TimeSpan.FromMinutes(5).Ticks));
答案 0 :(得分:0)
您可以尝试实现一个简单的 loop 而不是 Linq :
代码:
private static IEnumerable<TimeSpan[]> MyGrouping(IEnumerable<TimeSpan> source,
double minutes) {
List<TimeSpan> list = new List<TimeSpan>();
foreach (TimeSpan item in source.OrderBy(x => x)) {
// shall we start a new group?
if (list.Any() && (item - list.Last()).TotalMinutes > minutes) {
// if yes, return the previous
yield return list.ToArray();
list.Clear();
}
list.Add(item);
}
if (list.Any())
yield return list.ToArray();
}
演示:
var result = MyGrouping(hours, 5)
.Select((list, index) => $"Group {index + 1}: [{string.Join(", ", list)}]");
Console.Write(string.Join(Environment.NewLine, result));
结果:
Group 1: [10:35:50, 10:36:48, 10:41:48]
Group 2: [10:47:58, 10:49:14]
Group 3: [11:22:15, 11:24:18, 11:25:25]
答案 1 :(得分:0)
您可以通过使用Aggregate
确定每个时间段属于哪个“组”,然后GroupBy
来确定该组。
TimeSpan[] hours = new[] {
new TimeSpan(10,35,50),
new TimeSpan(10,36,48),
new TimeSpan(10,41,48),
new TimeSpan(10,47,58),
new TimeSpan(10,49,14),
new TimeSpan(11,22,15),
new TimeSpan(11,24,18),
new TimeSpan(11,25,25),
};
var query = hours.Aggregate(new List<(int group, TimeSpan ts)>(), (acc,curr) => {
if(acc.Count == 0)
acc.Add((0,curr));
else
{
var (lastGroup,lastTs) = acc.Last();
if(curr.Subtract(lastTs).TotalMinutes <= 5)
acc.Add((lastGroup,curr));
else
acc.Add((lastGroup+1,curr));
}
return acc;
}).GroupBy(x => x.group, y => y.ts);
foreach(var item in query)
Console.WriteLine(String.Join(", ", item));
输出为
10:35:50,10:36:48,10:41:48
10:47:58,10:49:14
11:22:15,11:24:18,11:25:25
实时示例:https://dotnetfiddle.net/zXhw0g
Aggregate
explained上的一个很好的问题,可以帮助您理解。
答案 2 :(得分:0)
您可以编写一种将项目分组的方法,如下所示:
public static IEnumerable<List<TimeSpan>> GroupItemsWithin(IEnumerable<TimeSpan> times, TimeSpan maxDelta)
{
var previous = TimeSpan.MinValue;
var spans = new List<TimeSpan>();
foreach (var span in times)
{
if (previous == TimeSpan.MinValue || (span - previous) <= maxDelta)
{
spans.Add(span);
}
else if (spans.Count > 0)
{
yield return spans;
spans = new List<TimeSpan>{ span };
}
previous = span;
}
if (spans.Count > 0)
yield return spans;
}
然后您可以像这样使用它:
public static void Main()
{
TimeSpan[] hours = new[] {
new TimeSpan(10, 35, 50),
new TimeSpan(10, 36, 48),
new TimeSpan(10, 41, 48),
new TimeSpan(10, 47, 58),
new TimeSpan(10, 49, 14),
new TimeSpan(11, 22, 15),
new TimeSpan(11, 24, 18),
new TimeSpan(11, 25, 25),
};
foreach (var group in GroupItemsWithin(hours, TimeSpan.FromMinutes(5)))
{
Console.WriteLine(string.Join(", ", group));
}
}
输出:
10:35:50,10:36:48,10:41:48
10:47:58,10:49:14
11:22:15,11:24:18,11:25:25
答案 3 :(得分:0)
如果要使用Linq。这是最简单的解决方案Demo
TimeSpan[] hours = new[]
{ new TimeSpan(10, 35, 50),
new TimeSpan(10, 36, 48),
new TimeSpan(10, 41, 48),
new TimeSpan(10, 47, 58),
new TimeSpan(10, 49, 14),
new TimeSpan(11, 22, 15),
new TimeSpan(11, 24, 18),
new TimeSpan(11, 25, 25), };
int groupID = -1;
var result = hours.OrderBy(h => h).Select((item, index) =>
{
if (index == 0 || (!(Math.Abs(hours[index - 1].Subtract(item).TotalMinutes) <= 5)))
++groupID;
return new { group = groupID, item = item };
}).GroupBy(item => item.group);