C# 仅使用LINQ对集合执行计算
我只想使用LINQ执行以下操作 我有一个带有用户进出时间的时间表条目列表。该类如下所示:C# 仅使用LINQ对集合执行计算,c#,linq,C#,Linq,我只想使用LINQ执行以下操作 我有一个带有用户进出时间的时间表条目列表。该类如下所示: public class TimeSheetLog { public Guid EmployeeId { get; set; } public DateTime ClockInTimeStamp { get; set; } public DateTime ClockOutTimeStamp { get; set; } } 我正在传递一个List(),其中包含年初至今的所有日志 我试图计算
public class TimeSheetLog
{
public Guid EmployeeId { get; set; }
public DateTime ClockInTimeStamp { get; set; }
public DateTime ClockOutTimeStamp { get; set; }
}
我正在传递一个List()
,其中包含年初至今的所有日志
我试图计算一月份的总工作时间——不管员工是谁。还请注意,我有一个名为GetTimeDifferenceInMinutes()
的函数,它计算两个日期/时间值之间的分钟数
这是我目前拥有的,但我觉得整个事情只能用LINQ来完成
public static int GetTotalTimeWorked(List<TimeSheetLog> logs, DateTime startDate, DateTime endDate)
{
// I'm passing 1/1/2018 for startDate and 1/31/2018 for endDate to this function
var totalTimeWorkedInMinutes = 0;
var januaryLogs = logs.Where(x => x.ClockInTimeStamp >= startDate &&
x.ClockOutTimeStamp <= endDate);
foreach(var item in januaryLogs)
{
totalTimeWorkedInMinutes += GetTimeDifferenceInMinutes(item.ClockInTimeStamp, itemClockOutTimeStamp);
}
return totalTimeWorkedInMinutes;
}
public static int GetTotalTimeWorked(列出日志、日期时间开始日期、日期时间结束日期)
{
//我将通过2018年1月1日的startDate和2018年1月31日的endDate来完成此功能
var totalTimeWorkedInMinutes=0;
var januaryLogs=logs.Where(x=>x.ClockInTimeStamp>=startDate&&
x、 ClockOutTimeStamp您需要总和
var tot = januaryLogs.Sum(item=>GetTimeDifferenceInMinutes(item.ClockInTimeStamp, itemClockOutTimeStamp));
你不能用求和的方法计算Where,然后在求和中进行DateTime减法,所以
decimal total = logs.Where(x => x.ClockInTimeStamp >= startDate && x.ClockOutTimeStamp <= endDate).Sum(x.ClockOutTimeStamp.Subtract(x.ClockInTimeStamp).TotalMinutes);
decimal total=logs.Where(x=>x.ClockInTimeStamp>=startDate&&x.ClockOutTimeStampvar logsFilteredByDate=logs.Where(x=>x.ClockInTimeStamp>=startDate)&&
x、 时钟输出时间戳
GetTimeDifferenceInMinutes(x.ClockInTimeStamp,x.ClockOutTimeStamp));
或者,将所有内容合并到一个查询中,这是不必要的,而且更难阅读
var totalTimeWorkedInMinutes = logs.Where(x => x.ClockInTimeStamp >= startDate &&
x.ClockOutTimeStamp <= endDate)
.Sum(x =>
GetTimeDifferenceInMinutes(x.ClockInTimeStamp, x.ClockOutTimeStamp));
var totalTimeWorkedInMinutes=日志。其中(x=>x.ClockInTimeStamp>=开始日期&&
x、 时钟输出时间戳
GetTimeDifferenceInMinutes(x.ClockInTimeStamp,x.ClockOutTimeStamp));
另一个选项是使用.Aggregate
函数
public static int GetTotalTimeWorked(List<TimeSheetLog> logs, DateTime startDate, DateTime endDate)
{
var totalTimeWorkedInMinutes = 0;
return logs.Where(x => x.ClockInTimeStamp >= startDate && x.ClockOutTimeStamp <= endDate)
.Aggregate(totalTimeWorkedInMinutes, (total, item) => total + GetTimeDifferenceInMinutes(item.ClockInTimeStamp, item.ClockOutTimeStamp));
}
public static int GetTotalTimeWorked(列出日志、日期时间开始日期、日期时间结束日期)
{
var totalTimeWorkedInMinutes=0;
返回日志。其中(x=>x.ClockInTimeStamp>=startDate和&x.ClockOutTimeStamp总计+GetTimeDifferenceInMinutes(item.ClockInTimeStamp,item.ClockOutTimeStamp));
}
除非你意识到时间表可以跨越几个月,否则这个问题似乎很容易解决。因此,如果有人在1月31日打卡,而在2月1日打卡,你必须计算部分时间表才能正确完成
以下是我的解决方案:
public static class ExtensionMethods
{
static public double TotalMinutes(this IEnumerable<TimeSheetLog> input, DateTime startPeriod, DateTime endPeriod)
{
return TimeSpan.FromTicks
(
input
.Where( a=>
a.ClockOutTimeStamp >= startPeriod &&
a.ClockInTimeStamp <= endPeriod
)
.Select( a=>
Math.Min(a.ClockOutTimeStamp.Ticks, endPeriod.Ticks) -
Math.Max(a.ClockInTimeStamp.Ticks, startPeriod.Ticks)
)
.Sum()
)
.TotalMinutes;
}
}
输出:
1320.00
…这是正确的
虽然聚合通常很有用,但Sum方法是一种专门用于计算总和的聚合器。这种方法不包括任何部分与开始日期或结束日期重叠的时间表,因此一些员工显然不会获得全额工资。如果你在1/31从晚上10点开始在墓地工作,你应该在一天内获得两小时的工资1月和2月的剩余时间。@JohnWu我只是回答如何使用已经提供的查询进行LINQ。您所指出的是有效的,但不是问题。问题是如何获取第一个查询的结果并使用LINQ求和。这对OP来说是一个很好的评论,但不在问题的范围之内。
public class Program
{
static public List<TimeSheetLog> testData = new List<TimeSheetLog>
{
new TimeSheetLog
{
ClockInTimeStamp = DateTime.Parse("1/1/2018 9:00 am"),
ClockOutTimeStamp = DateTime.Parse("1/1/2018 5:00 pm")
},
new TimeSheetLog
{
ClockInTimeStamp = DateTime.Parse("1/2/2018 9:00 am"),
ClockOutTimeStamp = DateTime.Parse("1/2/2018 5:00 pm")
},
new TimeSheetLog
{
ClockInTimeStamp = DateTime.Parse("1/31/2018 6:00 pm"),
ClockOutTimeStamp = DateTime.Parse("2/1/2018 9:00 am")
},
new TimeSheetLog
{
ClockInTimeStamp = DateTime.Parse("2/3/2018 9:00 am"),
ClockOutTimeStamp = DateTime.Parse("2/3/2018 5:00 pm")
}
};
public static void Main()
{
var startPeriod = new DateTime(2018, 1, 1);
var endPeriod = new DateTime(2018, 1, 31, 23, 59, 59, 9999);
Console.WriteLine( testData.TotalMinutes(startPeriod, endPeriod).ToString("0.00") );
}
}
1320.00