Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否有更有效的方法基于现有列表和查找列表创建列表?_C#_Refactoring - Fatal编程技术网

C# 是否有更有效的方法基于现有列表和查找列表创建列表?

C# 是否有更有效的方法基于现有列表和查找列表创建列表?,c#,refactoring,C#,Refactoring,我有下面的方法,它需要非常长的时间来运行,我希望能得到一些帮助,使它运行得更快或更高效 该方法的主要职责是获取从CSV文件创建的数据点列表,通过DataLoggerTagname属性将文件datapoints的Name属性映射到标记名列表中的to HistoriangName属性,并根据映射创建结果列表。如果映射不存在,则忽略文件数据点 我知道这是长篇大论,但我希望这是有道理的。只看一下方法可能更容易: private IEnumerable<DataPoint> GetHi

我有下面的方法,它需要非常长的时间来运行,我希望能得到一些帮助,使它运行得更快或更高效

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

我知道这是长篇大论,但我希望这是有道理的。只看一下方法可能更容易:

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

在这个循环中运行每个迭代都是一个非常昂贵的操作。

我首先要解决以下问题:

var historianTagname = historianTagnames.FirstOrDefault(x => x.DataLoggerTagname.Equals(fileDatapoint.Name, StringComparison.OrdinalIgnoreCase))
这是一个非常昂贵的操作,在这个循环中运行每个迭代。

就像@Sheldon Warkentin所说的FirstOrDefault可能是函数的瓶颈,我最好创建一个字典,其中Name是键,然后在函数中可以按键获得值

比如贝娄:

// this is passed to method
IDictionary<string, Tagname> historianTagnames;
// .. method body
var historianTagname = historianTagnames[fileDatapoint.Name];
当然,您需要添加适当的if。

如@Sheldon Warkentin所说,first或default可能是函数的瓶颈,我最好创建一个以Name为键的字典,然后在函数中按键获取值

比如贝娄:

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

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

以下是我的建议:

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;
        }
    }
}

以下是我的建议:

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;
        }
    }
}
正如其他人所说,词典可能会表现得更好

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()) {
        // ...
    }
}
正如其他人所说,词典可能会表现得更好

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()) {
        // ...
    }
}

如果有很多标记名,请对标记名使用口述。基本上,你会一遍又一遍地检查它们,Dictronial将节省一些计算量。你是否考虑过将你的名字存储到字典dic=新字典StringComparer.OrdinalIgnoreCase;然后用dic['yourkey']访问HistoriangName,我相信这会给你带来更好的性能?@AdolfoPerez:+1将StringComparer作为字典的相等比较者是个好主意。如果有很多标记名,请为HistoriangName使用口述。基本上,你会一遍又一遍地检查它们,Dictronial将节省一些计算量。你是否考虑过将你的名字存储到字典dic=新字典StringComparer.OrdinalIgnoreCase;然后用dic['yourkey']访问HistoryName,我相信这会给你带来更好的性能?@AdolfoPerez:+1将StringComparer作为字典的EqualityComparer传递给字典是个好主意。我非常喜欢Adolfo Perez的评论并更新了代码-我认为它现在更干净了。感谢完整的代码示例。使用字典,映射现在实际上是即时的。感谢所有贡献者!我真的很喜欢Adolfo Perez的评论并更新了代码-我认为现在代码更干净了。感谢完整的代码示例。使用字典,映射现在实际上是即时的。感谢所有贡献者!