我有一组日历事件对象,其日期值跨越多个学年,即201213 201112等 我需要首先将这些对象按年分组,因为该集合的第一个枚举是基于学年。然后我需要按月分组日期。 (这些月份也需要从当前日期开始倒退。然后,月份分组中的每个日期都需要从最晚到最早降序。
所以我正在与自己讨论这样做的最佳方式,我想到每年都有一个关键的学年指出词汇集合的价值。再次拥有一个月的密钥,然后是一组日历事件对象。
即。 dictionary<string, dictionary<string, List<CalendarEvent>>
我对此方法的一个担忧是排序并确保维护正确的顺序,因为对象将用于创建时间轴,其中时间轴上的第一个对象是最新的。 (以facebook时间轴为例,其中facebook事件按年,月和周分组,等等。)
上述系列是最好的,还是有一个更简单的解决方案或路径,我可能没有考虑过?
这个集合将被传递到一个MVC视图,所以在视图中对集合的按摩越少越好,这就是为什么我没有走下List的路径,日期也按学年分组从9月到6月,因此学年的字符串'201213'。所以我的目的是在集合中循环一次。
我打算循环遍历字典,再次通过字典循环中的每个项目循环几个月的内部字典,然后再循环通过实际的日历对象,为我提供时间线事件的时间顺序降序。 / p>
事件降序
即...
2013
七月
- 活动1月10日
- 7月1日活动
六月
- 活动x 6月30日
- 活动foo 6月1日
2012
四月
- 4月1日的活动栏
答案 0 :(得分:2)
对我来说,就像你过度使问题复杂化一样。如果你只是谈论几年的数据,你可以使用List<CalendarEvent>
的二维数组:
const int NumYears = 100;
const int BaseYear = 2012;
List<CalendarEvent>[,] MyEvents = new List<CalendarEvent>[NumYears, 12];
因此,要获得2014年1月的清单,请写下:
List<CalendarEvent> jan2014 = MyEvents[2014 - BaseYear, 0];
这不会占用大量空间,而且使用起来很简单。数组本身只占用100*12*(sizeof IntPtr)
个字节。因此,32位机器上的大约4,800个字节或64位机器上的9,600个字节。您分配的每个列表当然需要更多空间,但如果特定月份没有事件,则您无需支付该费用。如果大多数月份都有事件,这将比字典占用更少的空间。
如果你的学年是9月到6月并且你担心空间,你可以让第二级只有10个元素并且有方法可以将你的月/年(比如2014年1月)转换成适当的指数(我假设是2013学年的第4个月)。不过,我可能不会担心。我们只讨论了100年的数据的200个空引用。表达特殊条件可能需要超过该数量的代码。
就个别事件而言,某个月可能并不是很多,所以试图按时间顺序保留它们并不合理。只需在列表中执行OrderBy
即可按枚举日期排序。对少数事件进行排序不会花费任何可观的时间。
将所有内容包装在一个实现IEnumerable<CalendarEvent>
的类中并保证正确的枚举顺序应该很容易。
另一种选择是使用简单的List<CalendarEvent>
作为后备存储,并以任何顺序将事件抛入其中。然后,如果要显示特定学年或年份(甚至单个月或日期)的所有事件,您可以使用LINQ选择并按顺序(降序?)来选择所需的事件。这取决于您正在使用的事件总数,总数,以及您需要按摩它的次数。如果事件的总数是数千或甚至数万,则选择和排序将花费几毫秒。如果这些数字和我怀疑它们一样小,那么这可能是我的方式。
答案 1 :(得分:0)
不保证字典可以按任何特定顺序进行枚举。 SortedList或SortedDictionary集合的树可能会执行您要执行的操作。
也许您应该使用支持IComparable的集合(如List)。
答案 2 :(得分:0)
range tree,按时间键入点,可能是个更好的主意。这是关于他们的some helpful slides。
范围树需要更少的内务管理,因为树唯一关心的是确切的时间。它独立于人类构造,如月和年,这很好,因为人类构造是可怕的可怕事物(例如,由于时区,月份实际上在许多不同的时间结束)。在确定要查询的范围时,人类的东西才会出现。
答案 3 :(得分:0)
您应该尝试这个易于实施和维护的解决方案;使用:
SortedDictionary<YearMonth, Event>
YearMonth类应该实现IComparable,您可以在其中指定年份和月份具有降序。
干杯
答案 4 :(得分:0)
由于每个事件都有一个日期,你创建一个日期,并使用适当的一个和事件描述,我创建了一个calendarevent类和月枚举,以便于显示:
public enum NameOfMonth
{
january = 1,
febuary,
march,
april,
may,
june,
july,
august,
september,
october,
november,
december
}
class CalendarEvent
{
public NameOfMonth month;
public DateTime date { get; set; }
public string eventdescription { get; set; }
public CalendarEvent()
{
}
}
然后你创建一个包含每个calendarevent对象的列表(每个当然都带有描述,日期,等等......),然后按年份将其分组,创建一个匿名对象并按月排序,然后按天排序它只显示它们:
List<CalendarEvent> myevents = new List<CalendarEvent>()
{
new CalendarEvent(){date = new DateTime(2005,1,17),eventdescription = "Armaggedon",month = NameOfMonth.january},
new CalendarEvent(){date = new DateTime(2005,3,20),eventdescription = "Apocalypse",month = NameOfMonth.march},
new CalendarEvent(){date = new DateTime(2007,5,20),eventdescription = "WorldPeace",month = NameOfMonth.may},
new CalendarEvent(){date = new DateTime(2009,2,20),eventdescription = "LaundryDay",month = NameOfMonth.febuary},
new CalendarEvent(){date = new DateTime(2009,4,15),eventdescription = "MentalHealth",month = NameOfMonth.april},
new CalendarEvent(){date = new DateTime(2009,6,10),eventdescription = "ProgrammingInC#",month = NameOfMonth.june},
new CalendarEvent(){date = new DateTime(2009,6,12),eventdescription = "EraseAllYourWork?",month = NameOfMonth.june},
new CalendarEvent(){date = new DateTime(2010,10,20),eventdescription = "SomeVeryNiceEvent",month = NameOfMonth.october},
new CalendarEvent(){date = new DateTime(2010,8,21),eventdescription = "WellAnotherEvent",month = NameOfMonth.august}
};
var result = myevents2.GroupBy(d => d.date.Year)
.Select(g => new { Year = g.Key, data = g.OrderByDescending(k => k.date.Month).ThenByDescending(day => day.date.Day) })
.ToList();
foreach (var item in result)
{
Console.WriteLine("Events on ***" + item.Year + "***");
foreach (var subitems in item.data)
{
Console.WriteLine(subitems.month.ToString());
Console.WriteLine("On day " + subitems.date.Day + " - " + subitems.eventdescription);
}
}