有没有一种方法可以通过遍历日期列表来创建此报告?

时间:2020-06-19 02:37:37

标签: c# .net blazor

这是针对.net core 3.1应用程序,使用Blazor作为前端。

我有一个需要填写的日期列表,然后使用这些日期构建“分析”报告。分析基本上需要查看日期,并告诉我一周中的每一天有多少个日期,以及一年中的每个月有多少个日期。这是针对人力资源应用程序的,它们可以跟踪员工的缺勤情况。

我有一个已构建的列表,并将其传递给可以执行分析的方法。

public class DateHourResponseModel
    {
        public DateTime Date { get; set; }
        public int Hours { get; set; }
    }

我认为自己可以采用该列表,并创建“响应”列表,每个响应分别针对一周中的不同日期和一年中的月份。我想出了“类型”,我可以只使用DateTime.DayOfWeek,DateTime.Month并进入(星期几为0-6,每月为1-12),这就是为什么我上面有“ IsMonth”布尔值的原因。

public class AbsenceAnalysisResponse
{
    public int Type { get; set; }
    public bool IsMonth { get; set; }
    public int Count { get; set; }
    public int Hours { get; set; }
}

然后这个类,它只是上面的列表:

public class AbsenceAnalysis
{
     public List<AbsenceAnalysisResponse> Responses { get; set; }

}

我的问题是:有没有一种方法可以通过对开始的日期列表进行foreach来构建此分析报告?我没有想出一种创建列表的方法,而无需执行以下操作:

var analysisResponses = new List<AbsenceAnalysisResponse>
        {
            new AbsenceAnalysisResponse
            {
                Type = 0,
                IsMonth = false,
                Count = dateHourModel.Count(x => (int)x.Date.DayOfWeek == 0),
                Hours = dateHourModel.Where(x => (int)x.Date.DayOfWeek == 0).Sum(x => x.Hours)
            },

我觉得自己是个白痴,因为我知道必须有一种更优雅的方式来做到这一点,也许问题在于我是如何做到这一点的。我的分析工作在前端显示,但我绝对讨厌我如何创建“响应”列表。我对此还挺绿的,我不知道我是否只是没有在网上搜索正确的问题或什么,但是我还没有发现有人在做类似的事情。感谢您的帮助,如果需要提供任何信息,请告诉我。

2 个答案:

答案 0 :(得分:0)

类似的事情应该起作用:

var models = new List<DateHourResponseModel>(); //Should be a filled list, not empty like this
var modelMap = new Dictionary<(int, bool), AbsenceAnalysisResponse>();
foreach (DateHourResponseModel dateHour in models)
{
    Add(type: (int)dateHour.Date.DayOfWeek, isMonth: false);
    Add(type: dateHour.Date.Month, isMonth: true);


    void Add(int type, bool isMonth)
    {
        (int, bool) key = (type, isMonth);
        //Try to get existing responses
        if(!modelMap.TryGetValue(key, out AbsenceAnalysisResponse response))
        {
            //Create if first time adding to it
            modelMap[key] = response = new AbsenceAnalysisResponse
            {
                Type = type,
                IsMonth = isMonth,
                Count = 0,
                Hours = 0
            };
        }
        response.Count += 1;
        response.Hours += dateHour.Hours;
    }

}
//convert to list, can order if needed with .OrderBy()
List<AbsenceAnalysisResponse> analysisResponses = modelMap.Values.ToList();

这个想法是循环遍历每个模型并添加/修改列表。除了搜索列表之外,还可以将字典与唯一键一起使用。在这种情况下,以元组形式输入+ isMonth,但也可以是字符串“ {type}-{isMonth}”或其他形式。如果找不到密钥,则将创建密钥,否则将对其进行修改。最后,将“词典”变成其值的列表。还有其他方法,但这应该是一个好方法

答案 1 :(得分:0)

只是想发布我在修补时发现的另一个解决方案。我真的很喜欢Gekctek的答案,并在最初使用了它。我认为这一点可能更具可读性?很高兴收到任何反馈。

private AbsenceAnalysis GetAbsenceAnalysisFromData(List<DateHourResponseModel> dateHourModel)
    {
        var analysis = new List<AbsenceAnalysisResponse>();

        foreach (var data in dateHourModel)
        {
            var week = analysis.FirstOrDefault(x =>
                x.Type == (int)data.Date.DayOfWeek && x.IsMonth == false);
            var month = analysis.FirstOrDefault(x =>
                x.Type == (int)data.Date.Month && x.IsMonth == true);
            if (week == null)
            {
                week = new AbsenceAnalysisResponse
                {
                    Count = 0,
                    Hours = 0,
                    IsMonth = false,
                    Type = (int)data.Date.DayOfWeek
                };
                analysis.Add(week);
            }

            if (month == null)
            {
                month = new AbsenceAnalysisResponse
                {
                    Count = 0,
                    Hours = 0,
                    IsMonth = true,
                    Type = data.Date.Month
                };
                analysis.Add(month);
            }

            week.Count += 1;
            week.Hours += data.Hours;
            month.Count += 1;
            month.Hours += data.Hours;
        }