0

我有一个日历事件对象的集合,其日期值跨越多个学年,即 201213 201112 等我需要首先按年份对对象进行分组,因为该集合的第一个枚举是基于学年的. 然后我需要将日期按月分组。(月份也需要从当前日期向后运行。然后月份分组中的每个日期都需要从最新到最早的降序排列。

因此,我正在与自己讨论如何做到这一点的最佳方式,我被这样的想法所吸引,即每年都有一个学年的关键,这表明字典集合的价值,这些字典再次具有月份的键,然后是日历事件对象的集合。

IE。dictionary<string, dictionary<string, List<CalendarEvent>>

我对这种方法的一个担忧是排序并确保保持正确的顺序,因为对象将用于创建时间线,其中时间线上的第一个对象是最新的。(以 facebook 时间线为例,其中 facebook 事件按年、月和周等分组)。

上面的集合是最好的,还是有一个我可能没有考虑过的更简单的解决方案或路径?

该集合将被传递到 MVC 视图,因此视图中对集合的按摩越少越好,这就是为什么我没有走 List 的路径,日期也按跨度为 9 月的学年分组- June ,因此学年的字符串 '201213'。所以我的意图是循环一次通过集合。

我打算在字典中循环一次,并为字典中的每个项目再次循环通过月份的内部字典,然后再次循环通过实际日历对象,为我提供时间线的事件按时间降序排列的顺序。

随着事件的下降

IE ...

2013

七月

--事件 1 7 月 10 日

-- 活动 2 7 月 1 日

六月

-- 活动 x 6 月 30 日

-- 活动 foo 6 月 1 日

2012

四月

-- 活动栏 4 月 1 日

4

5 回答 5

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 选择和排序(降序?)来挑选您想要的。这实际上取决于您正在处理的事件总数以及您必须多久按摩一次。如果事件总数为数千甚至数万,则选择和排序将花费几毫秒。如果数字像我怀疑的那样小,这可能就是我要走的路。

于 2013-07-11T22:16:20.267 回答
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()
        {

        }
    }

然后你用每个日历事件对象创建一个列表(当然每个都有一个描述,日期等等......),然后按年分组它创建一个匿名对象并按月排序,然后按天排序,在它刚刚显示之后他们:

            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);
                }
            }
于 2013-07-12T03:10:04.767 回答
0

不保证字典以任何特定顺序进行枚举。SortedList 或 SortedDictionary 集合的树可能会做你想做的事情。

也许您应该使用支持 IComparable 的集合(如 List)。

于 2013-07-11T21:45:00.390 回答
0

以时间为键的范围树可能是一个更好的主意。这里有一些关于它们的有用幻灯片。

范围树将需要更少的内务管理,因为树唯一关心的是确切的时间。它独立于诸如月和年之类的人类构造,这很好,因为人类构造是可怕的可怕事物(例如,由于时区,几个月实际上在许多不同的时间结束)。只有在决定要查询的范围时,才会出现人为因素。

于 2013-07-11T21:45:24.987 回答
0

您应该尝试这种易于实施和维护的解决方案;用一个 :

SortedDictionary<YearMonth, Event>

YearMonth 类应实现 IComparable,您可以在其中指定年份和月份的降序排列。

干杯

于 2013-07-11T21:50:48.267 回答