2010-07-28 55 views
4

我有一個算法,可以掃描從.csv文件(約3700行)中讀取的數據,並通過爲每個星期日運行一次count ++來評估每個條目所在年度的哪一個交易周並在該日期落在該周內時將計數值指定爲交易周。「一週的一週」算法需要改進

它正在工作,但表現滯後。這是使用Task.Factory.StartNew運行的第三個函數(我也嘗試了parallel.Invoke)。

時間測試的結果。

前:00:00:05.58

後:00:00:23.27

UPDATE

新增突破每一個交易周設置後。時間改善但仍然緩慢。

新的時間:00:00:15.74

對於我們來說今年的第一週爲1周(不爲0),並定義爲從當年的第一天,直到星期天。如果一年的第一天是星期天,那麼第一週的時間是1天。

private void SetDefiniteWeeks() 
     { 
      string FileLoc = FilePath + Market + ".csv"; 
      string[] Data = File.ReadAllLines(FileLoc); 
      var FileData = from D in Data 
          let DataSplit = D.Split(',') 
          select new 
          { 
           Date = DateTime.Parse(DataSplit[0]), 
           ClosingPrice = double.Parse(DataSplit[4]) 
          }; 

      //assign each date to it's relevant week 
      TradingWeek TW; 
      List<TradingWeek> tradingWeek = new List<TradingWeek>(); 
      foreach (var pe in FileData) 
      { 
       // DateTime dt = pe.Date; 
       int Year = pe.Date.Year; 
       string End_of_Week = "Sunday"; 
       int WeekCount = 0; 

       DateTime LoopDate_Begin = new DateTime(Year,1,1); 
       DateTime LoopDate_End = new DateTime(Year,12,31); 
       do 
       { 
        if (LoopDate_Begin.DayOfWeek.ToString() == End_of_Week) 
        { 
         WeekCount++; 
         if (LoopDate_Begin.DayOfYear > pe.Date.DayOfYear && LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7)) 
         { 
          TW = new TradingWeek { Week = WeekCount, Date = pe.Date }; 
          tradingWeek.Add(TW); 
          break; 
         } 
        } 
        LoopDate_Begin = LoopDate_Begin.AddDays(1); 

       } while (LoopDate_Begin.Date.ToString() != LoopDate_End.Date.ToString()); 

      } 

     } 

請幫忙。

UPDATE

NEW TIME

00:00:06.686

一個巨大的進步。感謝你的幫助。

修改後的代碼:

CalendarWeekRule cw = CalendarWeekRule.FirstDay; 
    var calendar = CultureInfo.CurrentCulture.Calendar; 
    var trad_Week = (from pe in FileData 
         select new TradingWeek 
         { 
         Date = pe.Date, 
         Week = (calendar.GetWeekOfYear(pe.Date, cw,DayOfWeek.Sunday)) 
         }).ToList(); 

回答

4

林不知道如果這是你想要什麼,但看完後評論我的感覺是,這可能工作

var calendar = CultureInfo.CurrentCulture.Calendar; 
var tradingWeek = (from pe in FileData 
        select new TradingWeek 
        { 
        Date = pe.Date, 
        Week = calendar.GetWeekOfYear(pe.Date, CalendarWeekRule.FirstDay, DayOfWeek.Sunday); 
        }).ToList(); 

編輯(?):改到CalendarWeekRule.FirstDay因爲它的(更?)OP正在尋找什麼。

+0

Jesper我不確定這是否會由於CalendarWeekRule而產生正確的結果。請參閱我的更新。 – Chris 2010-07-28 18:02:58

+0

@Chris:如果使用CalendarWeekRule.FirstDay會怎麼樣? – 2010-07-28 18:35:12

+0

謝謝Jesper,檢查了過去幾年的第一天,值都是正確的! – Chris 2010-07-28 19:40:03

1

,如果我讓你正確,你並不需要儘快看任何進一步爲您添加您的TradingWeek

所以,你可以

break; 

tradingWeek.Add(TW); 

你可以那麼即使離開了

&& LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7) 

條件,因爲第一部分將是真實的,只有一次:你想要的時間間隔。

+0

Break;再加上謝謝。查看原始更新的新時間 – Chris 2010-07-28 16:54:44

4

三點快速的想法:

  • 爲什麼你只有一天每次加和檢查,看它是否是星期天。當然,一旦你找到你的第一個星期天,你可以添加七天來找到下一個星期日?

  • 如果您在開始之前通過DateTime訂購您的pes,那麼您無需在每年的年初重新開始,您可以從中斷位置繼續。

  • 正如尼古拉斯所說,加入交易周後突破。在你已經知道答案是什麼之後,無需經過剩餘的時間。

我猜你會擁有這樣的事情(可能或可能不實際工作,但應儘量接近)

TradingWeek TW; 
List<TradingWeek> tradingWeek = new List<TradingWeek>(); 
string End_of_Week = "Sunday"; 
var orderedData = FileData.OrderBy(x => x.Date) 
DateTime LoopDate_Begin = new DateTime(orderedData[0].Date.Year,1,1); 
int WeekCount = 1; 

while (LoopDate_Begin.DayOfWeek.ToString() != End_of_Week) 
{ 
    LoopDate_Begin = LoopDate_Begin.AddDays(1); 
} 

foreach (var pe in orderedData) 
{ 
    do 
    {   
     if (LoopDate_Begin.DayOfYear > pe.Date.DayOfYear && LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7)) 
     { 
      TW = new TradingWeek { Week = WeekCount, Date = pe.Date }; 
      tradingWeek.Add(TW); 
      break; 
     } 
     WeekCount++; 
     LoopDate_Begin = LoopDate_Begin.AddDays(7); 

    } while (true); //need to be careful here 

} 
+0

感謝Martin,orderedData [0] .Date.Year給了我一個錯誤: 錯誤無法對[]類型的System.Linq.IOrderedEnumerable ' – Chris 2010-07-28 17:09:16

+0

請嘗試orderedDate.First()。Date.Year代替。 – 2010-07-28 17:14:31

+2

一個微不足道的問題,但是爲什麼最終將它與DayOfWeek枚舉進行比較時,爲什麼要將End_Of_Week存儲在字符串中呢? DayOfWeek的最佳選擇End_Of_Week = DayOfWeek.Sunday; ... LoopDate_Begin.DayOfWeek!= End_of_Week – DonaldRay 2010-07-28 18:09:26

1

你甚至可能會去一個無迴路的方法通過將自開始一週以來的天數減少了7天 - 並做了一些清理工作;)

+1

我同意;並且無法理解如何解決方案正在「優化」循環方法。澤勒的勝利一致! – 2010-07-28 18:25:46

1

您可以通過直接計算星期數來擺脫您的do循環嗎?像接受的答案here

+3

如果這是一個選項,您可以使用內置函數:CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(someDate,CalendarWeekRule.FirstFourDayWeek,DayOfWeek.Sunday) – 2010-07-28 17:26:27

+0

非常好。甚至不知道存在。 – 2010-07-28 17:29:44

0

根本不需要計算 - 只需快速計算。這假設在一年的開始部分周是第一週,第一週和第二週開始。

List<TradingWeek> tradingWeek = new List<TradingWeek>(); 
foreach (var pe in FileData) 
{ 
    var date = pe.Date; 
    while (date.DayOfWeek != DayOfWeek.Sunday) 
     date = date.AddDays(1); 
    var week = date.DayOfYear/7+1; 
    var TW = new TradingWeek {Week = week, Date = pe.Date}; 
    tradingWeek.Add(TW); 
} 
1

繼@ nicolas78的迴應,這樣的事情應該工作

int Year = pe.Date.Year; 
DateTime Year_Begin = new DateTime(Year,1,1); 
int Jan1DayOfWeek = Year_Begin.DayOfWeek; 

foreach (var pe in FileData) 
{ 
    int WeekCount = (pe.Date.DayOfYear - Jan1DayOfWeek) % 7 + 1; 
    TradingWeek TW = new TradingWeek { Week = WeekCount, Date = pe.Date }; 
    tradingWeek.Add(TW); 
} 

根據星期幾和DAYOFYEAR怎麼算,也就是從0或1,以及如何你的MOD操作的工作,你可能需要調整WeekCount計算一下。

0

有一個內置功能可以基於.NET中的日期獲取一年的一週。下面顯示了一個示例,但它可能需要進行一些調整以適合您的業務場景:

System.Globalization.CultureInfo myCI = new System.Globalization.CultureInfo("en-US"); 

int week = myCI.Calendar.GetWeekOfYear(DateTime.Now.ToUniversalTime(), System.Globalization.CalendarWeekRule.FirstFourDayWeek, System.DayOfWeek.Sunday); 
相關問題