Wpf &引用;“年度工作周”;算法需要改进

Wpf &引用;“年度工作周”;算法需要改进,wpf,algorithm,c#-4.0,Wpf,Algorithm,C# 4.0,我有一个算法,可以扫描从.csv文件(大约3700行)读取的数据,并通过在该年的每个星期日运行count++来评估每个条目在一年中的哪个交易周,当日期在该周内时,将计数值指定为交易周 它正在工作,但性能落后。这是使用Task.Factory.StartNew运行的第三个函数(我也尝试过parallel.Invoke) 定时测试的结果 00:00:05.58之前 在:00:00:23.27之后 更新 在设定每个交易周后增加休息时间。时间有所改善,但仍然缓慢 新时间:00:00:15.74 就我们而

我有一个算法,可以扫描从.csv文件(大约3700行)读取的数据,并通过在该年的每个星期日运行count++来评估每个条目在一年中的哪个交易周,当日期在该周内时,将计数值指定为交易周

它正在工作,但性能落后。这是使用Task.Factory.StartNew运行的第三个函数(我也尝试过parallel.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());

            }

        }

如果我没记错的话,你不需要在加入TradingWeek后再看下去

所以,你可以

break;
之后

tradingWeek.Add(TW);
然后你甚至可以省略

&& LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7)
和&LoopDate\u Begin.DayOfYear<(pe.Date.DayOfYear+7)
条件,因为第一部分只有一次为真:对于您想要的间隔。

三个快速想法:

  • 为什么你每次只增加一天,看看是不是星期天。当然,一旦你找到了你的第一个星期天,你可以再加上七天来找到下一个星期天

  • 如果您在开始之前按日期时间订购您的pes,那么您不需要在年初为每一个pes重新启动,您可以从您停止的地方开始

  • 正如尼古拉斯所说,在增加交易周后休息。在你已经知道答案之后,就不需要经历今年剩下的时间了

我猜你最终会得到这样的结果(可能有效,也可能无效,但应该足够接近)

TradingWeek TW;
List tradingWeek=新列表();
字符串结束\u Week=“Sunday”;
var orderedData=FileData.OrderBy(x=>x.Date)
DateTime LoopDate_Begin=新的日期时间(orderedData[0]。日期。年份,1,1);
int WeekCount=1;
while(LoopDate\u Begin.DayOfWeek.ToString()!=周末)
{
LoopDate\u Begin=LoopDate\u Begin.AddDays(1);
}
foreach(orderedData中的变量pe)
{
做
{           
if(LoopDate\u Begin.dayof year>pe.Date.dayof year&&LoopDate\u Begin.dayof year<(pe.Date.dayof year+7))
{
TW=新交易周{Week=WeekCount,Date=pe.Date};
交易周。增加(TW);
打破
}
WeekCount++;
LoopDate\u Begin=LoopDate\u Begin.AddDays(7);
}虽然(正确);//这里需要小心
}

您甚至可以采用无环方法,将开始一周的天数除以7,然后进行一些清理工作;)

通过直接计算周数,你能完全摆脱你的
do
循环吗?类似于公认的答案。

你根本不需要数数,只需快速计算即可。这假设年初的部分周为第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);
}
List tradingWeek=新列表();
foreach(FileData中的var-pe)
{
var日期=pe.日期;
while(date.DayOfWeek!=DayOfWeek.Sunday)
日期=日期。添加天数(1);
var week=日期。DayOfYear/7+1;
var TW=新交易周{Week=Week,Date=pe.Date};
交易周。增加(TW);
}

我不确定这是否是你想要的,但在阅读了评论后,我觉得这可能会奏效(?)


编辑:更改为CalendarWeekRule.FirstDay,因为它是OP想要的(更多?)。

在@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),以及mod操作的工作方式,您可能需要稍微调整WeekCount计算。

有一个内置功能,可以根据.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);

感谢Martin,orderedData[0]。Date.Year给了我一个错误:错误2无法将带[]的索引应用于“System.Linq.IORDerenumerable”类型的表达式,请改为尝试orderedDate.First().Date.Year。这是一件小事,但当您最终将它与DayOfWeek枚举进行比较时,为什么要将“周末的结束”存储在字符串中?最好是周末结束=周末周日。。。LoopDate\u Begin.DayOfWeek!=如果这是一个选项,您可以使用内置函数:CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(someDate,CalendarWeekRule.FirstFourDayWeek,DayOfWeek.Sunday)非常好。Jesper我不确定这是否会产生正确的结果,因为CalendarWeekRule。请查看我的更新。@克里斯:如果您使用CalendarWeekRule.FirstDay怎么办?谢谢Jesper,检查了过去几年的第一天,值都是正确的!我同意;而且无法理解“优化”循环方法的解决方案是如何被提升的。泽勒对胜利的祝贺!
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();
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);
}
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);