Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
GTA
0 / 0 / 0
Регистрация: 12.09.2013
Сообщений: 2
1

Есть ли более простой и оптимальный способ решения данной задачи?

12.09.2013, 15:54. Просмотров 1089. Ответов 2
Метки нет (Все метки)

Добрый день! Ситуация следующая:

Есть класс Event.

C#
1
2
3
4
5
6
public class Event 
{
    public string Name { get; set; }
    public Period Plan { get; set; }
    public Period Fact { get; set; }
}
В нем есть поля класса Period.

C#
1
2
3
4
5
6
public class Period
{
    public bool isPeriod { get; set; }
    public DateTime From { get; set; }
    public DateTime To { get; set; }
}
Т.е. тут либо период дат некоторого события (isPeriod=1, период From - To), либо точная дата события (isPeriod=0, From-точная дата).
Plan - планируемая дата, Fact - фактическая (могут пересекаться).

Есть List<Event> в котором есть объекты Event, содержащие как точные даты, так и периоды. Необходимо получить в заданном ограничении dateFrom - dateTo, Dictionary<DateTime, int> , где DateTime - некоторая дата, int - количество событий на эту дату.

Я сделал это двумя способами, но оба они мне не нравятся. Есть ощущение, что можно сделать проще и оптимальнее. Буду очень рад, если подскажите как. Также буду рад любым советам и комментариям по коду.

1. Перебираем List<Event>.
В теле цикла получаем hashSet<DateTime> для каждого рассматриваемого события.
Добавляем в Dictionary<DateTime, int> даты из hashSet<DateTime>, увеличивая при этом int для каждой даты.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public Dictionary<DateTime, int> Example()
{
    var events = new List<Event>();
    DateTime dateFrom, dateTo;
 
        ...
 
    var resultDic = new Dictionary<DateTime, int>();
 
    foreach (var ev in events)
    {
        var dateSet = new HashSet<DateTime>();
        //plan
        dateSet.UnionWith(GetFullRange(ev.Plan).Where((d) => d >= dateFrom && d <= dateTo));
        //fact
        dateSet.UnionWith(GetFullRange(ev.Fact).Where((d) => d >= dateFrom && d <= dateTo));
 
        foreach (var date in dateSet)
        {
            if (!(resultDic.ContainsKey(date)))
            {
                resultDic.Add(date, 1);
            }
            else
            {
                resultDic[date]++;
            }
        }
    }
 
    return resultDic;
}
 
//Метод для получения HashSet
private HashSet<DateTime> GetFullRange(Period period)
{
    var resultHashSet = new HashSet<DateTime>();
 
    resultHashSet.Add(period.From);
    if (period.isPeriod)
    {
        for (DateTime date = period.From.AddDays(1.0); date <= period.To; date = date.AddDays(1.0))
        {
            resultHashSet.Add(date);
        }
    }
    return resultHashSet;
}
2. Второй способ подробно описывать не буду, приведу код. Сразу скажу, что этот способ совсем мне не нравится. Смысл тут в том, что перебирая List<Events>, мы рассматриваем все случаи попадания периода в заданные ограничения.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
public Dictionary<DateTime, int> Example()
        {
            var events = new List<Event>();
            var dateFrom = new DateTime();
            var dateTo = new DateTime();
 
            //...
 
            var resultDic = new Dictionary<DateTime, int>();
            var dic = new Dictionary<DateTime, HashSet<Event>>();
 
            foreach (var ev in events)
            {
                //plan
                //точная дата 
                if (!ev.Plan.isPeriod)
                {
                    if (ev.Plan.From >= dateFrom && ev.Plan.From <= dateTo)
                    {
                        checkDate(ev.Plan.From, ref dic, ev);
                    }
                }
                //период 
                else
                {
                    //период попадает в календарь
                    if (ev.Plan.From >= dateFrom && ev.Plan.To <= dateTo)
                    {
                        for (DateTime date = ev.Plan.From; date <= ev.Plan.To; date = date.AddDays(1.0))
                        {
                            checkDate(date, ref dic, ev);
                        }
                    }
                    //период частично попадает в календарь в начало временного отрезка
                    else if (ev.Plan.From < dateFrom && ev.Plan.To <= dateTo)
                    {
                        for (DateTime date = dateFrom; date <= ev.Plan.To; date = date.AddDays(1.0))
                        {
                            checkDate(date, ref dic, ev);
                        }
                    }
                    //период частично попадает в календарь в конец временного отрезка
                    else if (ev.Plan.From >= dateFrom && ev.Plan.To > dateTo)
                    {
                        for (DateTime date = ev.Plan.From; date <= dateTo; date = date.AddDays(1.0))
                        {
                            checkDate(date, ref dic, ev);
                        }
                    }
                }
                //fact
 
                //точная дата 
                if (!ev.Fact.isPeriod)
                {
                    if (ev.Fact.From >= dateFrom && ev.Fact.From <= dateTo)
                    {
                        checkDate(ev.Fact.From, ref dic, ev);
                    }
                }
                //период 
                else
                {
                    //период попадает в календарь
                    if (ev.Fact.From >= dateFrom && ev.Fact.To <= dateTo)
                    {
                        for (DateTime date = ev.Fact.From; date <= ev.Fact.To; date = date.AddDays(1.0))
                        {
                            checkDate(date, ref dic, ev);
                        }
                    }
                    //период частично попадает в календарь в начало временного отрезка
                    else if (ev.Fact.From < dateFrom && ev.Fact.To <= dateTo)
                    {
                        for (DateTime date = dateFrom; date <= ev.Fact.To; date = date.AddDays(1.0))
                        {
                            checkDate(date, ref dic, ev);
                        }
                    }
                    //период частично попадает в календарь в конец временного отрезка
                    else if (ev.Fact.From >= dateFrom && ev.Fact.To > dateTo)
                    {
                        for (DateTime date = ev.Fact.From; date <= dateTo; date = date.AddDays(1.0))
                        {
                            checkDate(date, ref dic, ev);
                        }
                    }
                }
                //days.EventsCount.Add(ev.Date, ev.Count);
                foreach (var d in dic)
                {
                    resultDic[d.Key] = d.Value.Count();
                }
            }
            return resultDic;
        }
 
        //Проверка и заполнение
        private void checkDate(DateTime date, ref Dictionary<DateTime, HashSet<Event>> dic, Event ev)
        {
            if (!dic.ContainsKey(date))
            {
                dic.Add(date, new HashSet<Event>());
                dic[date].Add(ev);
            }
            else
            {
                dic[date].Add(ev);
            }
        }
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.09.2013, 15:54
Ответы с готовыми решениями:

Найти более оптимальный способ решения задачи
Вот задача: Имеется две таблицы: 1) Items (Id identity(1,1) int, Name varchar(50)) в которой ...

Кригинг - есть ли библиотеки для решения данной задачи за более "быстрое" время
Реализован кригинг, но решается за длительное время, особенно в 3d-пространстве. Есть ли библиотеки...

Можно ли написать более оптимальный или простой код, используя цикл for?
собственно сабж. #include &lt;iostream&gt; using namespace std; int main() { int sum, count,...

Замена двух строк в огромном файле. Есть ли оптимальный способ?
Есть задача, поменять в огромном текстовом файле (несколько Гб) 2 произвольные строки. Написал 2 ...

Более простой способ создания форм
Ищу более простой способ создания форм на WinApi без использования ресурсов и.т.п. Может есть какая...

2
kmaffa
314 / 307 / 150
Регистрация: 29.10.2012
Сообщений: 850
12.09.2013, 16:18 2
Цитата Сообщение от GTA Посмотреть сообщение
Т.е. тут либо период дат некоторого события (isPeriod=1, период From - To), либо точная дата события (isPeriod=0, From-точная дата).
Скажите пожалуйста, период дат - это значит событие будет идти все эти дни включая эти дни или может начаться в какой то из дней этого периода?
Цитата Сообщение от GTA Посмотреть сообщение
Plan - планируемая дата, Fact - фактическая (могут пересекаться).
Можно тут поподробнее, они как бы и должны пересекаться?
Цитата Сообщение от GTA Посмотреть сообщение
Есть List<Event> в котором есть объекты Event, содержащие как точные даты, так и периоды. Необходимо получить в заданном ограничении dateFrom - dateTo, Dictionary<DateTime, int> , где DateTime - некоторая дата, int - количество событий на эту дату.
Можете объяснить следующую ситуацию: например надо выбрать даты с 10 по 20 число, а есть 2 события с периодами:
первое: с 5 по 15
второе с 16 по 25
Что должно быть на выходе?

При выборке учитывать только планируемые даты или фактические тоже?
0
GTA
0 / 0 / 0
Регистрация: 12.09.2013
Сообщений: 2
12.09.2013, 18:05  [ТС] 3
Цитата Сообщение от kmaffa Посмотреть сообщение
Скажите пожалуйста, период дат - это значит событие будет идти все эти дни включая эти дни или может начаться в какой то из дней этого периода?
Все эти дни

Цитата Сообщение от kmaffa Посмотреть сообщение
Можете объяснить следующую ситуацию: например надо выбрать даты с 10 по 20 число, а есть 2 события с периодами:
первое: с 5 по 15
второе с 16 по 25
Что должно быть на выходе?
resultDictionary[DateTime.Parse("10.mm.yy")]=1
resultDictionary[DateTime.Parse("11.mm.yy")]=1
...
resultDictionary[DateTime.Parse("20.mm.yy")]=1

но если выборка с 10 по 30 то
первое: с 12 по 18 планируемые даты, 20 - фактическая
второе с 16 по 25 планируемые даты, 23 фактическая
то

resultDictionary[DateTime.Parse("10.mm.yy")]=0 (на эту дату нет событий)
resultDictionary[DateTime.Parse("11.mm.yy")]=0 -//-
resultDictionary[DateTime.Parse("12.mm.yy")]=1 (на эту дату одно событие - первое, планируемая дата)
...
resultDictionary[DateTime.Parse("15.mm.yy")]=1 -//-
resultDictionary[DateTime.Parse("16.mm.yy")]=2 (на эту дату 2 события, первое - планируемая дата, второе - планируемая дата)
resultDictionary[DateTime.Parse("17.mm.yy")]=2 -//-
resultDictionary[DateTime.Parse("18.mm.yy")]=2 -//-
resultDictionary[DateTime.Parse("19.mm.yy")]=1 (на эту дату одно событие - второе, планируемая дата)
resultDictionary[DateTime.Parse("20.mm.yy")]=2 (на эту дату 2 события, первое - фактическая дата, второе - планируемая дата)
resultDictionary[DateTime.Parse("21.mm.yy")]=1 (на эту дату одно событие - второе, планируемая дата)
resultDictionary[DateTime.Parse("22.mm.yy")]=1 -//-
resultDictionary[DateTime.Parse("23.mm.yy")]=1 (на эту дату одно событие - второе, фактическая и планируемая даты совпадают)
...

Цитата Сообщение от kmaffa Посмотреть сообщение
Можно тут поподробнее, они как бы и должны пересекаться?
Могут пересекаться, могут не пересекаться. Т.е. событие может быть запланировано с 5 по 15, а факт наступления - 20 (или с 20 по 22).

Цитата Сообщение от kmaffa Посмотреть сообщение
При выборке учитывать только планируемые даты или фактические тоже?
И планируемые и фактические
0
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.09.2013, 18:05

Ищу оптимальный код для решения одной задачи
Добрый день, друзья! У меня есть одна задача с табличными данными, которую я в принципе могу решить...

Какой способ лучше для решения данной системы дифуров?
Привет!) У меня проблемка, не могу решить системы дифуров численно. Система:...

Способ решения задачи
Подскажите пожалуйста, каким методом можно решить данную задачу? Спасибо.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.