C# 提高数组查找循环性能

我有一个Datapoint[] file = new Datapoint[2592000]数组。这个数组充满了时间戳和随机值。创建它们需要花费我 2 秒的时间。但是在另一个函数中,prepareData();我正在为另一个 Array 准备 240 个值TempBuffer。在prepareData()函数中,我正在搜索file数组中的匹配值。如果我找不到任何我取时间戳并将值设置为 0 否则我取找到的值 + 相同的时间戳。


该函数如下所示:


public void prepareData()

{  

    stopWatch.Reset();

    stopWatch.Start();

    Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;


    for (double i = unixTimestamp; unixTimestamp - 240 < i; i--)

    {

        bool exists = true;


        if (exists != (Array.Exists(file, element => element.XValue == i)))

        {

            TempBuffer = TempBuffer.Skip(1).Concat(new DataPoint[] { new DataPoint(UnixTODateTime(i).ToOADate(), 0) }).ToArray();

        }

        else

        {

            DataPoint point = Array.Find(file, element => element.XValue == i);

            TempBuffer = TempBuffer.Skip(1).Concat(new DataPoint[] { new DataPoint(UnixTODateTime(i).ToOADate(), point.YValues) }).ToArray();

        }

    }


    stopWatch.Stop();

    TimeSpan ts = stopWatch.Elapsed;

}

现在的问题是file函数需要 40 秒的(2'592'000) 中的数据量!对于 10'000 等较小的数量,这不是问题,并且可以正常快速地工作。但是一旦我将file大小设置为我喜欢的 2'592'000 点,CPU 就会被推到 99% 的性能并且该功能需要的时间太长。


TempBuffer 样本值:

X = UnixTimeStamp 转换为 DateTime 和 DateTime 转换为 AODate

{X=43285.611087963, Y=23}


文件样本值:

X = Unixtimestamp

{X=1530698090, Y=24}


将临时缓冲区值转换为 AODate 很重要,因为临时缓冲区数组内的数据显示在 mschart 中。


有没有办法改进我的代码,以便我获得更好的性能?


炎炎设计
浏览 319回答 3
3回答

婷婷同学_

这是您的任务最高效的方式(这只是一个模板,而不是最终代码):public void prepareData(){&nbsp; &nbsp; // it will be initialized with null values&nbsp; &nbsp; var tempbuffer = new DataPoint[240];&nbsp; &nbsp; var timestamp = (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;&nbsp; &nbsp; var oldest = timestamp - 240 + 1;&nbsp; &nbsp; // fill tempbuffer with existing DataPoints&nbsp; &nbsp; for (int i = 0; i < file.Length; i++)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (file[i].XValue <= timestamp && file[i].XValue > timestamp - 240)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempbuffer[file[i].XValue - oldest] = new DataPoint(file[i].XValue, file[i].YValues);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // fill null values in tempbuffer with 'empty' DataPoints&nbsp; &nbsp; for (int i = 0; i < tempbuffer.Length; i++)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; tempbuffer[i] = tempbuffer[i] ?? new DataPoint(oldest + i, 0);&nbsp; &nbsp; }}我有大约 10 毫秒从评论更新:如果您想获取多个DataPoint's并使用某个函数(例如平均值)获得结果,则:public void prepareData(){&nbsp; &nbsp; // use array of lists of YValues&nbsp; &nbsp; var tempbuffer = new List<double>[240];&nbsp; &nbsp; // initialize it&nbsp; &nbsp; for (int i = 0; i < tempbuffer.Length; i++)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; tempbuffer[i] = new List<double>(); //set capacity for better performance&nbsp; &nbsp; }&nbsp; &nbsp; var timestamp = (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;&nbsp; &nbsp; var oldest = timestamp - 240 + 1;&nbsp; &nbsp; // fill tempbuffer with existing DataPoint's YValues&nbsp; &nbsp; for (int i = 0; i < file.Length; i++)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (file[i].XValue <= timestamp && file[i].XValue > timestamp - 240)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempbuffer[file[i].XValue - oldest].Add(file[i].YValues);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // get result&nbsp; &nbsp; var result = new DataPoint[tempbuffer.Length];&nbsp; &nbsp; for (int i = 0; i < result.Length; i++)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; result[i] = new DataPoint(oldest + i, tempbuffer[i].Count == 0 ? 0 : tempbuffer[i].Average());&nbsp; &nbsp; }}

米脂

您还没有向我们提供您代码的完整图片。理想情况下,我希望示例数据和完整的类定义。但是考虑到可用的限制信息,我认为您会发现这样的工作:public void prepareData(){&nbsp;&nbsp; &nbsp; Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;&nbsp; &nbsp; var map = file.ToLookup(x => x.XValue);&nbsp; &nbsp; TempBuffer =&nbsp; &nbsp; &nbsp; &nbsp; Enumerable&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Range(0, 240)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Select(x => unixTimestamp - x)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .SelectMany(x =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map[x]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Concat(new DataPoint(UnixTODateTime(x).ToOADate(), 0)).Take(1))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .ToArray();}
打开App,查看更多内容
随时随地看视频慕课网APP