是否有更有效的方法来基于现有列表和查找列表创建列表
本文关键字:列表 于现 查找 创建 有效 方法 是否 | 更新日期: 2023-09-27 18:33:23
我有以下方法,需要很长时间才能运行,并希望得到一些帮助,以使其运行得更快或更高效。
该方法的主要职责是获取从 CSV 文件创建的数据点列表,将文件数据点的 Name
属性映射到 DataLoggerTagname
属性的标记名列表中的 to HistorianTagname
属性,并从映射创建结果列表。 如果映射不存在,则忽略文件数据点。
我知道这是啰嗦的,但我希望这是有道理的。 仅查看方法可能更容易:
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;
}
}
}
笔记:我可以完全控制映射的类和方法,所以如果我做错了什么。 我很想知道!
谢谢!
我会从修复开始:
var historianTagname = historianTagnames.FirstOrDefault(x => x.DataLoggerTagname.Equals(fileDatapoint.Name, StringComparison.OrdinalIgnoreCase))
通过此循环运行每次迭代是一项非常昂贵的操作。
以下是我的主张:
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;
}
}
}
就像 @Sheldon Warkentin说FirstOrDefault
可能是你的函数的瓶颈,我最好创建historianTagnames一个Dictionary
,其中Name是键,然后在你的函数中你可以按键获取值。
像波纹管这样的东西:
// this is passed to method
IDictionary<string, Tagname> historianTagnames;
// .. method body
var historianTagname = historianTagnames[fileDatapoint.Name];
当然,您需要添加适当的if。
正如其他人所说,Dictionary<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()) {
// ...
}
}