字典词典是最好的解决方案吗?

时间:2013-07-11 21:40:15

标签: c# collections

我有一组日历事件对象,其日期值跨越多个学年,即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日的活动栏

5 个答案:

答案 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);
                }
            }