那是我的代码:
class Data
{
public DateTime Date { get; private set; }
public int Income { get; private set; }
public Data(DateTime date, int income)
{
Date = date;
Income = income;
}
}
public static List<Data> GetSampleData()
{
var now = DateTime.Now.Date;
return new List<Data>()
{
new Data(now.AddMinutes(-15), 15), //23:45
new Data(now.AddMinutes(-30), 10), //23:30
new Data(now.AddMinutes(-45), 7), //23:15
new Data(now.AddMinutes(-55), 8), //23:05
new Data(now.AddMinutes(-62), 0), //23:58
new Data(now.AddMinutes(-67), 12), //22:53
new Data(now.AddMinutes(-70), 1), //22:50
};
}
我想在哪个小时获得最高的收入。带有示例数据,它应该给我以下结果:
Income: 33
Hour: 23
我所管理的是这个
var data = GetSampleData();
var result = data.GroupBy(x => new
{
hour = x.Date.Hour
})
.Select(z => new
{
Sum = z.Sum(a => a.Income),
Hour = z.Key.hour
})
.OrderByDescending(x => x.Sum)
.FirstOrDefault();
这正在工作。但是由于OrderByDescending
,我不喜欢我的解决方案。有没有更好的方法来解决这个问题?如果可能的话,我想使用Max
解决方案,但是我无法编写代码。会是:
Get max sum of incomes from groups
答案 0 :(得分:1)
在较新的.NET版本中,可以使用C# 7.0 tuple types(总和必须是第一个元组项):
var result = data.GroupBy(d => d.Date.Hour)
.Max(g => (Sum: g.Sum(d => d.Income), Hour: g.Key));
或作为单独的变量:
(int Sum, int Hour) = data.GroupBy(d => d.Date.Hour)
.Max(g => (g.Sum(d => d.Income), g.Key));
在较旧的.NET版本中,System.Tuple<T1,T2>
:
var result = data.GroupBy(d => d.Date.Hour)
.Max(g => Tuple.Create(g.Sum(d => d.Income), g.Key));
如果一个以上的元组具有最大总和,则结果为具有最大小时数的元组。
不带元组的更有效的替代方法可能是对两个值使用相同的数字:
int maxSumHour = data.GroupBy(d => d.Date.Hour)
.Max(g => g.Sum(d => d.Income) * 100 + g.Key));
int Sum = maxSumHour / 100, Hour = maxSumHour % 100;
答案 1 :(得分:0)
您可以使用Aggregate:
.Aggregate( (curMax, x) => (curMax == null) || (x.Sum > curMax.Sum) ? x : curMax );
答案 2 :(得分:0)
在我看来,您的工作还不错,因为您可以在相同的最高收入下拥有一个多小时。话虽如此,您始终可以使用Aggregate
:
var sums = data.GroupBy(d => d.Date.Hour)
.Select(g => new { hour = g.Key, sum = g.Sum(d => d.Income) });
var maxData = sums.Aggregate(
sums.FirstOrDefault(), //First parameter
(max, next) => next.sum > max.sum ? next : max, //Second parameter
sum => sum //Third parameter
);
说明:
Aggregate
函数使用种子作为第一个参数,在这种情况下,它是总和的第一项。如果您检查maxData
,它将使用属性hour
和sum
聚合类型。
答案 3 :(得分:0)
如果您真的想使用Max()解决方案,请不要使用匿名类型,而是先创建一个类/结构并实现IComparable
public struct IncomePerHour : IComparable<IncomePerHour>
{
public int Income { get; set; }
public int Hour { get; set; }
public int CompareTo(IncomePerHour other)
{
return Income.CompareTo(other.Income);
}
}
然后,不要使用您选择的匿名结果,而是将其设为您刚创建的类/结构。
var data = GetSampleData();
var result = data.GroupBy(x => x.Date.Hour)
.Select(z => new IncomePerHour
{
Income = z.Sum(a => a.Income),
Hour = z.Key
})
.Max();
如果您想重复使用数据:
public class Data : IComparable<Data>
{
public DateTime Date { get; private set; }
public int Income { get; private set; }
public Data(DateTime date, int income)
{
Date = date;
Income = income;
}
public int CompareTo(Data other)
{
return Income.CompareTo(other.Income);
}
}
class Program
{
var data = GetSampleData();
var result = data.GroupBy(x => x.Date.Hour)
.Select(z => new Data (z.First().Date, z.Sum(a => a.Income)))
.Max();
Console.WriteLine($"Hour: {result.Date.Hour}, Income:{result.Income}");
}