处理日历项目时要使用哪种数据结构? [英] What kind of data structure to use when working with calendar items?
问题描述
您好,我正在使用.NET框架进行日历项目,并且在处理日期时遇到了可怕的性能问题.问题是,每当我要检索在特定日期发生的所有事件和待办事项时,都必须查看事件和待办事项的整个列表,以检查在该日期发生了哪些事件和/或待办事项.当我处理项目任务时,问题也会变得更加严重.因此,它是3 O(n).
通常,在这种情况下,我将使用排序的二叉树数据结构作为存储而不是列表,但是当重复发生时,我不知道如何对它们进行排序.因此,我需要一些有关如何提高检索特定日期发生的所有项目的性能的建议.同样,此数据结构必须能够处理事件和/或待办事项''日期更改时的情况.
很难仅显示有关该项目的相关细节,而又不会用细节压倒这个问题,但是我会尝试一下.我目前将四个不同的组件集成在一起:
- MonthCalendar类库
- DDay.iCal类库,用于使用iCal文件
-Microsoft Office Project 12.0对象库
-插件框架
Microsoft Office Project 12.0对象库将通过其中一个插件来应用. 标准中详细解释了什么是事件,待办事项和重复发生.可以在维基百科上找到一个简短的简短摘要.
使用事件处理程序,每次我在MonthCalendar上选择一个日期时,请执行以下操作:
Hi, I am working on a calendar project using .NET framework and is running into a horrible performance issue when working with dates. The issue is that whenever I want to retrieve all the events and to-dos occurring on a particular date, I have to transverse the entire list of events and to-dos checking which events and/or to-dos occur on that date. The problem gets worse when I work with project tasks as well. Thus, it is 3 O(n).
Typically, in this kind of situation, I would use a sorted binary tree data structure as storage rather than a list, but I don''t know how to sort them when recurrence occurs. Thus, I need some recommendation on how I can improve the performance for retrieving all items occurring on a particular date. Also, this data structure must be able to handle situation when events'' and/or to-dos'' date is changed.
It is kind of hard to show just only relevant details about the project without overwhelming this question with details, but I will give it a try. I am integrating currently four different components together:
- MonthCalendar class library
- DDay.iCal class library for using iCal file
- Microsoft Office Project 12.0 Object Library
- Plug-In Framework
Microsoft Office Project 12.0 Object Library will be applied via one of the plug-ins. What is events, to-dos, and recurrence is explained in details on this standard. A simple and short version summary can be found on Wikipedia.
Using the event handler, every time I select a date on MonthCalendar, execute the following:
private void calendar_DaySelected(object sender, DaySelectedEventArgs e)
{
DateTime date = DateTime.Parse(e.Days[0]);
schedulePanel.EventList.Clear();
schedulePanel.EventList.AddRange(calendarPanel.Calendar.GetDateInfo(date));
schedulePanel.TodoList.Clear();
schedulePanel.TodoList.AddRange(todoPanel.GetDateInfo(date));
if (projectPlugins.Count > 0)
{
schedulePanel.Tasks.Clear();
for (int i = 0; i < projectPlugins.Count; i++)
{
schedulePanel.Tasks.AddRange(projectPlugins[i].GetDateInfo(date));
}
}
schedulePanel.Update(date);
}
这是SchedulePanel的部分类代码:
Here is the partial class code for SchedulePanel:
public SchedulePanel()
{
InitializeComponent();
eventList = new List<Library.DateItem>();
taskList = new List<PluginSDK.ITask>();
todoList = new List<ITodo>();
}
public void Update(DateTime date)
{
Text = "Schedule for " + date.ToShortDateString();
eventGridView.Rows.Clear();
//Display Occurring Events
for (int i = 0; i < eventList.Count; i++)
{
eventGridView.Rows.Add();
eventGridView.Rows[i].Cells[0].Value = eventList[i].Event.Summary;
}
//Display Occurring Project Tasks
if (taskList.Count != 0)
{
if (!this.Controls.Contains(this.taskBox))
{
this.Controls.Add(this.taskBox);
this.todoBox.Location = new System.Drawing.Point(3, 232);
this.todoBox.Size = new System.Drawing.Size(193, 116);
}
taskListBox.Items.Clear();
for (int j = 0; j < taskList.Count; j++)
{
taskListBox.Items.Add(taskList[j].Name);
}
}
else
{
if (this.Controls.Contains(this.taskBox))
{
this.Controls.Remove(this.taskBox);
this.todoBox.Location = new System.Drawing.Point(3, 103);
this.todoBox.Size = new System.Drawing.Size(193, 236);
}
}
//Display Occurring To-dos
todoListBox.Items.Clear();
for (int i = 0; i < todoList.Count; i++)
{
todoListBox.Items.Add(todoList[i].Summary);
}
}
public List<Library.DateItem> EventList
{
get
{
return eventList;
}
}
public List<ITodo> TodoList
{
get
{
return todoList;
}
}
public List<PluginSDK.ITask> Tasks
{
get
{
return taskList;
}
}
这是TodoPanel的部分类代码:
Here is the partial class code for TodoPanel:
public List<ITodo> GetDateInfo(DateTime date)
{
List<ITodo> todos = new List<ITodo>();
for (int i = 0; i < todoList.Count; i++)
{
if (todoList[i].Status != TodoStatus.Completed)
{
if (todoList[i].Start != null && todoList[i].Start.Date <= date)
todos.Add(todoList[i]);
else if (todoList[i].Due != null && todoList[i].Due.Date <= date)
todos.Add(todoList[i]);
}
}
return todos;
}
这是使用Microsoft Office Project 12.0对象库的MSProjectPanel的部分类代码:
Here is the partial class code for MSProjectPanel using Microsoft Office Project 12.0 Object Library:
public List<ITask> GetDateInfo(DateTime date)
{
List<ITask> tasks = new List<ITask>();
foreach (Project project in application.Projects)
{
foreach (Task task in project.Tasks)
{
if (task.OutlineChildren.Count == 0 && task.Status != PjStatusType.pjComplete)
{
if (CompletePrerequisite(task) && DateTime.Parse(task.Start.ToString()) <= date)
{
tasks.Add(new ProjectTask(task));
}
}
}
}
return tasks;
}
在运行带有512 MB RAM的Microsoft XP Professional的2.16GHz计算机上选择新日期后,大约需要3秒钟以上的时间才能完成执行.当前,我正在使用3个iCal文件和2个MPP文件.那应该是大约150多个项目(事件,待办事项和100多个项目任务)的总和.如果没有MSProject插件,它将下降到1+秒.
It takes about 3+ seconds to finish executing after selecting a new date on 2.16GHz computer running Microsoft XP Professional with 512 MB of RAM. Currently, I am using 3 iCal files and 2 MPP files. That should be about 150+ items (events, to-dos, and 100+ project tasks) combined. Without MSProject plugin, it drops down to 1+ second.
推荐答案
要处理在一周中给定日期发生的重复发生的事件,只需保留一周中的某天值(以7为模的天索引)而不是完整日期.
要处理在每月的给定日期发生的重复事件,只需保留每月的日期值而不是整个日期即可.
依此类推.
To handle recurring events that occur on a given day of the week, just keep the day of the week value (day index modulo 7) instead of the full date.
To handle recurring events that occur on a given day of the month, just keep the day of the month value instead of the full date.
And so on.
这篇关于处理日历项目时要使用哪种数据结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!