Алгоритм «Неделя года» нуждается в доработке - PullRequest
4 голосов
/ 28 июля 2010

У меня есть алгоритм, который просматривает данные, считанные из файла .csv (около 3700 строк), и оценивает, в какую торговую неделю года входит каждая запись, выполняя count ++ для каждого воскресенья этого года и назначая значение count какторговая неделя, когда дата попадает в эту неделю.

Работает, но производительность отстает.Это третья функция, запущенная с использованием Task.Factory.StartNew (я также пробовал параллельный. Invoke).

Результаты временных тестов.

до: 00: 00: 05.58

после: 00: 00: 23.27

ОБНОВЛЕНИЕ

Добавлен перерыв после установки каждой торговой недели.Время улучшилось, но все еще медленно.

новое время: 00: 00: 15,74

Для наших целей первая неделя года - это неделя 1 (не 0), и она определяется с первого днягода до воскресенья.Если первый день года - воскресенье, продолжительность недели 1 составляет 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());

            }

        }

Пожалуйста, помогите.

ОБНОВЛЕНИЕ

НОВОЕ ВРЕМЯ

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

Ответы [ 8 ]

4 голосов
/ 28 июля 2010

Я не уверен, что это то, что вам нужно, но после прочтения комментариев у меня возникло ощущение, что это может сработать (?)

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, поскольку это (больше?)что ищет ОП.

4 голосов
/ 28 июля 2010

Три быстрых мысли:

  • Почему вы добавляете только один день каждый раз и проверяете, не воскресенье ли это.Конечно, как только вы нашли свое первое воскресенье, вы можете добавить семь дней, чтобы найти следующее?

  • Если вы заказываете свои pes по DateTime до начала, вам не нужно перезапускать вначало года для каждого из них, вы можете узнать, где остановились.

  • Как говорит Николас, перерыв после добавления торговой недели.Нет необходимости проходить остаток года после того, как вы уже знаете, какой ответ.

Я полагаю, у вас получится что-то вроде этого (может или не может работать,но должно быть достаточно близко)

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

}
1 голос
/ 28 июля 2010

После ответа @ 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);
}

В зависимости от того, как рассчитываются DayOfWeek и DayOfYear, то есть от 0 или 1, и от того, как работает ваша мода, вам может потребоваться настроитьWeekCount вычисление немного.

1 голос
/ 28 июля 2010

Можете ли вы вообще избавиться от цикла do, рассчитав номер недели напрямую? Что-то вроде принятого ответа здесь .

1 голос
/ 28 июля 2010

Вы могли бы даже пойти на подход без петель, разделив число дней с вашей начальной недели на 7 - и выполняя некоторую работу по уборке;)

1 голос
/ 28 июля 2010

если я правильно вас понял, вам не нужно больше смотреть, как только вы добавите свой TradingWeek

Итак, вы можете

break;

после

tradingWeek.Add(TW);

Вы могли бы даже пропустить условие

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

, поскольку первая часть будет истинной только один раз: для желаемого интервала.

0 голосов
/ 28 июля 2010

Существует встроенная функция для получения недели года на основе даты в .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);
0 голосов
/ 28 июля 2010

Вам не нужно считать вообще - просто сделайте быстрый расчет. Это предполагает, что неполная неделя в начале года - это неделя 1, а неделя 2 начинается в первый понедельник.

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...