2013-07-11 41 views
0

我有一個日曆事件對象的集合,其日期值跨越多個學年,即201213 201112等 我需要首先將對象按年分組,因爲集合上的第一個枚舉基於學年。然後我需要按月分組日期。 (月份也需要從當前日期後退,然後月份分組中的每個日期都需要按照從最新到最早的順序遞減字典詞典是最好的解決方案嗎?

因此,我正在與自己討論如何做到這一點的最佳方式,我想到每年都有一個學年的關鍵,它指向一個詞典集合的價值,這個詞典的集合又有一個月的關鍵詞,然後是一個日曆事件對象集合。

dictionary<string, dictionary<string, List<CalendarEvent>>

我對這種方法的一個擔心是排序和確保正確的順序維護,因爲這些對象將用於創建時間線,whe重新在時間軸上的第一個對象是最新的。 (以facebook時間線爲例,其中facebook事件按年,月和周等分組)。

上述集合是最好的,還是有更簡單的解決方案或路徑我可以下去,我可能沒有考慮過?

這個集合將被傳遞給一個MVC視圖,所以視圖中集合的按摩越少越好,這就是爲什麼我沒有走下List的路徑,日期也按照學術跨越九月至六月的一年,因此學年爲字符串「201213」。所以我的意圖是循環一次通過集合。

我打算循環一次通過詞典和字典循環中的每個項目再次通過月的內部字典然後通過實際的日曆對象循環再次爲我提供時間線的事件按時間順序降序。

隨着降

即事件......

--event 1 7月10日

- 事件2 7月1日

六月

- 事件X 6月30日

- 事件foo的6月1日

- 事件條4月1日

+0

請定義「更好」可以回答這個問題。請注意,您目前的方法明顯處於「壞」的一面,因爲您似乎正在使用字符串作爲數字數據(年份通常是「int」,而不是「字符串」)。 –

+1

這完全取決於你將如何使用這些對象。您可以將它們放在一個直式列表中,並在需要時隨時用LINQ進行分組/排序。不知道你的使用模式是什麼,這個問題不是很有意義。 – Jon

+0

我與Jon共享相同的想法,列表或類似可能已足夠用LINQ的orderby等 – Sayse

回答

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個月)。不過,我可能不會擔心。我們只談及200年的空值參考資料。它可能需要更多的代碼才能表達特殊情況。

就個人事件而言,在某個月可能並不是很多,所以按照時間順序排列並不合理。只需在列表上按日期排序OrderBy,以便列舉它們。對少量事件進行排序不會花費任何可觀的時間。

它應該很容易包裝在一個實現IEnumerable<CalendarEvent>並保證正確的枚舉順序的類中。

另一種選擇是使用簡單的List<CalendarEvent>作爲後備存儲,並以任意順序將事件放入其中。然後,如果您想顯示特定學年或一系列年份(甚至是單個月份或日期)的所有事件,則可以使用LINQ選擇並按(降序?)排序以挑選出您想要的。這實際上取決於多少事件,總數,您正在使用的以及您需要多久進行一次按摩。如果事件的總數是幾千甚至幾萬,那麼選擇和排序將花費毫秒。如果數字和我猜想的一樣小,這可能就是我的選擇。

+0

謝謝吉姆我會給它一個旋轉,我希望我提出的解決方案是錯綜複雜的。 –

+1

這是一種讓我喜歡StackOverflow的評論。讓不同的大腦考慮一個策略和現實 - 爲你檢查它是非常有價值的。這是一個很好的分析,並有可能爲OPer節省很多工作和痛苦。做得好。 – Curt

+0

@MikeRayner:查看我的更新。一個簡單的'List '可能是要走的路。 –

0

字典不能保證枚舉任何特定的順序。 SortedList或SortedDictionary集合的樹可能會做你想做的事情。

也許你應該使用支持IComparable的集合(如List)。

+0

您可以在字典上使用'OrderBy',然後枚舉它將按照您指定的順序進行。 – aevitas

+0

只能通過Linq。 – Curt

+0

只能通過Linq?只要首先對字典進行排序,就可以按照特定的順序使用'foreach'來枚舉它。 – aevitas

0

A range tree,以時間爲關鍵點,可能是一個更好的主意。這裏是關於他們的some helpful slides

範圍樹需要很少的家務管理,因爲樹唯一關心的是確切的時間。它獨立於人類的構造,如月和年,這很好,因爲人類的構造是可怕的可怕事物(例如,由於時區,月份實際上在許多不同的時間結束)。只有在確定要查詢的範圍時,人的東西纔會進入畫面。

0

您應該嘗試這個易於實施和維護的解決方案;使用:

SortedDictionary<YearMonth, Event> 

的YearMonth類應該實現IComparable,在那裏你可以指定年,月有一個從大到小的順序。

乾杯

+0

這看起來更有利,我沒有考慮可以同時使用年份和月份來獲得我需要的鑰匙。我會試試看看它是否提供了我需要的結果。 –

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