1

我有以下方法需要很长时间才能运行,并且希望得到一些帮助以使其运行得更快或更高效。

该方法的主要职责是获取从 CSV 文件创建的数据点列表,Name将文件数据点的属性映射到属性HistorianTagname的标记名列表中的DataLoggerTagname属性,并从映射中创建结果列表。如果映射不存在,则忽略文件数据点。

我知道那是冗长的,但我希望这是有道理的。只看方法可能更容易:

    private IEnumerable<DataPoint> GetHistorianDatapoints(IEnumerable<DataPoint> fileDatapoints, IEnumerable<Tagname> historianTagnames)
    {
        /**
         ** REFACTOR THIS 
         **/

        foreach (var fileDatapoint in fileDatapoints)
        {
            var historianTagname = historianTagnames.FirstOrDefault(x => x.DataLoggerTagname.Equals(fileDatapoint.Name, StringComparison.OrdinalIgnoreCase));
            if (historianTagname != null)
            {
                var historianDatapoint = new DataPoint();

                historianDatapoint.Name = historianTagname.HistorianTagname;
                historianDatapoint.Date = fileDatapoint.Date;
                historianDatapoint.Value = fileDatapoint.Value;

                yield return historianDatapoint;
            }
        }
    }

注意:我可以完全控制映射的类和方法,所以如果我做的事情根本上是错误的。我愿意知道!

谢谢!

4

4 回答 4

4

我将从修复开始:

var historianTagname = historianTagnames.FirstOrDefault(x => x.DataLoggerTagname.Equals(fileDatapoint.Name, StringComparison.OrdinalIgnoreCase))

通过此循环运行每次迭代是一项非常昂贵的操作。

于 2012-05-04T16:11:53.750 回答
2

就像@Sheldon Warkentin所说FirstOrDefault的可能是您的功能的瓶颈,最好创建 historianTagnames 一个Dictionary名称是关键的地方,然后在您的功能中您可以按键获得价值。

像下面这样:

// this is passed to method
IDictionary<string, Tagname> historianTagnames;
// .. method body
var historianTagname = historianTagnames[fileDatapoint.Name];

当然,您需要添加适当的 if。

于 2012-05-04T16:15:51.943 回答
2

下面是我的提议:

private IEnumerable<DataPoint> GetHistorianDatapoints(IEnumerable<DataPoint> fileDatapoints, IEnumerable<Tagname> historianTagnames)
{
    var tagNameDictionary = historianTagnames.ToDictionary(t => t.DataLoggerTagname, StringComparer.OrdinalIgnoreCase);

    foreach (var fileDatapoint in fileDatapoints)
    {                
        if (tagNameDictionary.ContainsKey(fileDatapoint.Name))
        {
            var historianTagname = tagNameDictionary[fileDatapoint.Name];
            var historianDatapoint = new DataPoint();

            historianDatapoint.Name = historianTagname.HistorianTagname;
            historianDatapoint.Date = fileDatapoint.Date;
            historianDatapoint.Value = fileDatapoint.Value;

            yield return historianDatapoint;
        }
    }
}
于 2012-05-04T16:19:41.480 回答
0

正如其他人所说,aDictionary<string, Tagname>可能会表现得更好。

var historianDict = new Dictionary<string, Tagname>();
foreach (var tagName in historianTagnames) {
    historianDict[tagName.DataLoggerTagname.ToLowerInvariant()] = tagName;
}

foreach (var fileDatapoint in fileDatapoints) {
    if (historianDict.ContainsKey(fileDatapoint.Name.ToLowerInvariant()) {
        // ...
    }
}
于 2012-05-04T16:22:17.900 回答