如何优化更改深度嵌套在对象图中的值的代码

时间:2016-09-02 06:45:25

标签: c# performance linq

下面是一个粗略的for循环来说明我需要做什么。

基本上,如果有任何'变量'具有财产的对象'名称'包含文本" TCC#",然后我想更改'类型'属性(不是.Net类型)到' VariableType.Text'。

代码将运行4800个ParsedCard变量,并且当前需要花费大量时间(大约10分钟)来简单地遍历列表并将一行写入调试控制台。

ParsedCard has 
IEnumberable Functions which have 
IEnumberable Groups which have 
ParseResults which have 
IEnumberable Variables

这是一个很简单的问题,但是我已经尝试过使用LINQ的各种变体,但是找不到效果不错的东西(不到10秒)。

    private void AdjustTCCVariables(IList<ParsedCard> parsedCards)
    {    
        for (var i = 0; i < parsedCards.Count; i++)
        {
            var parsedCard = parsedCards[i];
            for (var j = 0; j < parsedCard.Functions.Count(); j++)
            {
                var function = parsedCard.Functions.ToList()[j];
                for (var k = 0; k < function.Groups.Count(); k++)
                {
                    var group = function.Groups.ToList()[k];
                    for (var l = 0; l < group.ParseResult.Variables.Count(); l++)
                    {
                        var variable = group.ParseResult.Variables.ToList()[l];
                        if (variable.Name.Contains("TCC#"))
                        {
                            //variable.Type = VariableType.Text;
                            Debug.WriteLine($"Need to change variable at [{i}][{j}][{k}][{l}]");
                        }
                    }
                }
            }
        }
    }

我已尝试使用此LINQ但它实际上并没有更改变量。类型&#39;输入列表(我怀疑是因为它在内存中创建了一个新的对象副本,并且赋值实际上并没有影响到&#39; parsedCards&#39; IEnumerable:

    private void AdjustTCCVariables(IEnumerable<ParsedCard> parsedCards)
    {
        var targetVariables =
            parsedCards.SelectMany(x => x.Functions.SelectMany(z => z.Groups))
                .SelectMany(x => x.ParseResult.Variables.Where(v => v.Name.Contains("TCC#")));
        ;
        foreach (var variable in targetVariables)
        {
            variable.Type = VariableType.Text;
        }
    }

2 个答案:

答案 0 :(得分:2)

如上所述,迭代中的瓶颈是.ToList()次调用。

由于您提到您只想编辑variable.Type属性,我会像这样解决这个问题。

var variables = from parsedCard in parsedCards
                from function in parsedCard.Functions
                from group in function.Groups
                from variable in group.ParseResult.Variables
                where variable.Name.Contains("TCC#")
                select variable;

foreach (var variable in variables) {
    variable.Type = VariableType.Text;
}

除了需要更改的variable对象之外,您不需要知道任何其他内容,也不需要所有索引和所有其他变量。只需选择您需要知道的内容并进行更改即可。

这样您就不会知道索引,因此Debug.WriteLine(...);行无效。

答案 1 :(得分:0)

不知道课程的定义,这里有一些提示。 删除toList,不要依赖迭代(for statement)

int numberOf = parsedCards.Count
 for (var i = 0; i < numberOf; i++)
        {
            //var parsedCard = parsedCards[i];
            int noOf2 = parsedCard[i].Functions.Count()
            for (var j = 0; j < noOf2; j++)
            {
                var function = parsedCard[i].Functions[j];

                int = function.Groups.Count();
                for (var k = 0; k < noOfGroups; k++)
                {
                    var group = function.Groups[k];
                    int noOfVars = group.ParseResult.Variables.Count();
                    for (var l = 0; l < noOfVars; l++)
                    {
                        var variable = group.ParseResult.Variables[l];
                        if (variable.Name.Contains("TCC#"))
                        {
                            //variable.Type = VariableType.Text;
                            Debug.WriteLine($"Need to change variable at [{i}][{j}][{k}][{l}]");
                        }
                    }
                }
            }
        }