Есть ли способ создать этот отчет, перебирая список дат? - PullRequest
1 голос
/ 19 июня 2020

Это для приложения. 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 для месяца), поэтому у меня есть bool «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 голосов
/ 19 июня 2020

Просто хотел опубликовать другое решение, которое я нашел, пока возился с этим. Мне очень понравился ответ 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;
        }
0 голосов
/ 19 июня 2020

Что-то вроде этого должно работать:

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();

Идея состоит в том, чтобы oop пройти через каждую модель и добавить / изменить список. Вместо поиска по списку можно использовать словарь с уникальным ключом. В этом случае введите + isMonth в форме кортежа, но это также может быть строка "{type} - {isMonth}" или что-то в этом роде. Если ключ не найден, он будет создан, в противном случае просто изменен. В конце превратите Словарь в список его значений. Есть и другие способы сделать это, но это должно быть хорошим подходом

...