复杂的LINQ查询与复杂的循环

时间:2014-03-11 11:28:21

标签: c# algorithm linq dictionary

现在我有这个复杂的函数,我有一个MainObjects列表(称之为MO),对于每个对象,我必须循环一个对象列表(称为C),标题,状态和子对象列表(称为E)。该函数循环遍历这些子对象(E)并使用它的标题和数量属性。

该函数的目标是创建一个字典(D1),其中Key是C(标题),而Values是另一个字典(D2),其中Key是E(标题),而Values是另一个字典(D3),其中Key为C(状态),值为E(数量)。 所以最后我将拥有所有(独特的)C(标题),其中我可以看到所有(独特的)E(标题)其中我可以看到所有不同的C(状态)&#39 ; s和这些状态的E(数量)(如果2 E(数量)在相同的路线上具有相同的标题,则应作为额外的挑战,它们应相互添加然后放入作为价值)。

我把这一切都搞好了。

然而。功能很大,很难理解,所以我正在寻找一种更平易近人的方法来处理这个问题。 其中一种方式应该是LINQ。但是,我几乎不知道这个以及大量复杂的功能,因为我很难理解如何在LINQ中处理这个问题。 我也关注性能,因为这个WPF项目非常依赖用户体验。因此,我不确定LINQ是否会让事情更快,更慢或相同。

这是你们进来的地方。

  • LINQ是解决此问题的更好方法吗?

  • 性能是否与我的功能相似?

  • LINQ查询是否更容易理解?

  • 是否有另一种处理这种复杂功能的方法
    而不是我描述的两种方法?


在下面你会找到我用来处理这个功能的函数。

分3步完成:

  1. 第1步:循环MO,C,E,并创建一个词典列表。

  2. 步骤2:加入步骤1结果的重复键,然后创建一个 第一阶段词典。

  3. Step3:拆分更深层次的词典 我们可以按预期使用E对象。
  4. 结果:已经进入了#final;'宾语。带有键C(标题)的字典列表,并列出字典列表。这个字典列表具有键E(标题)和值字典。该词典具有键C(状态)和值E(数量)。该E(数量)是相同C的相同C(状态)的每个E的每个数量的组合值。


            //DateTime start = DateTime.Now; //start performance test
    
            //start -> step 1
            List<Dictionary<string/*C(title)*/, Dictionary<int/*C(status)*/, List<E>>>> firstResultList = new List<Dictionary<string, Dictionary<int, List<E>>>>();
    
            foreach(MO mo in listOfMOs)
            {
                foreach (C c in mo.listOfCs)
                {
                    Dictionary<string, Dictionary<int, List<E>>> D1 = new Dictionary<string, Dictionary<int, List<E>>>();
    
                    int cStatus = c.status;
                    Dictionary<int, List<E>> D2 = new Dictionary<int, List<E>>();
    
                    List<E> eList = new List<E>();
    
                    foreach (E e in c.listOfEs)
                    {
                        eList.Add(e);
                    }
    
                    D2.Add(cStatus, eList);
    
                    D1.Add(c.Title, D2);
    
                    firstResultList.Add(D1);
                }
            }
            //firstResultList = step1 results
            //Console.WriteLine(firstResultList.ToString());
            //
    
            //step1 -> step2
            Dictionary<string/*C(title)*/, List<Dictionary<int/*C(status)*/, List<E>>>> groupedDict = new Dictionary<string, List<Dictionary<int, List<E>>>>();
    
            foreach (Dictionary<string, Dictionary<int, List<E>>> dict in firstResultList)
            {
                List<Dictionary<int, List<E>>> listje;
    
                if(groupedDict.ContainsKey(dict.Keys.ElementAt(0)))
                {
                   listje = groupedDict[dict.Keys.ElementAt(0)];
    
                }
                else
                {
                    listje = new List<Dictionary<int, List<E>>>();
                }
    
                listje.Add(dict[dict.Keys.ElementAt(0)]);
                groupedDict[dict.Keys.ElementAt(0)] = listje;
            }
            //groupedDict = step2 results
            //Console.WriteLine(groupedDict.ToString());
            //
    
            //step2 -> step3
            Dictionary<string/*C(title)*/, List<Dictionary<string/*E(title)*/, Dictionary<int/*C(status)*/, int/*E(quantity)*/>>>> final = new Dictionary<string, List<Dictionary<string, Dictionary<int, int>>>>();
    
            int index = 0;
            foreach (List<Dictionary<int, List<E>>> list in groupedDict.Values)
            {
                //Within one unique C
                List<Dictionary<string, Dictionary<int, int>>> eStatusQuantityList = new List<Dictionary<string, Dictionary<int, int>>>();
    
                foreach (Dictionary<int, List<E>> dict in list)
                {
                    foreach (List<E> eList in dict.Values)
                    {
                        foreach(E e in eList)
                        {
                            if (eStatusQuantityList.Count > 0)
                            {
                                foreach (Dictionary<string, Dictionary<int, int>> dict2 in eStatusQuantityList)
                                {
                                    Dictionary<int, int> statusQuantityDict;
    
                                    if (dict2.ContainsKey(e.Title))
                                    {
                                        statusQuantityDict = dict2[e.Title];
                                        //int quantity = statusQuantityDict.value//statusQuantityDict[dict.Keys.ElementAt(0)];
                                        int quantity = 0;
                                        int value;
                                        bool hasValue = statusQuantityDict.TryGetValue(dict.Keys.ElementAt(0), out value);
                                        if (hasValue) {
                                            quantity = value;
                                        } else {
                                            // do something when the value is not there
                                        }
    
                                        statusQuantityDict[dict.Keys.ElementAt(0)] = quantity + e.Quantity;
                                        dict2[e.Title] = statusQuantityDict;
                                    }
                                    else
                                    {
                                        statusQuantityDict = new Dictionary<int, int>();
                                        statusQuantityDict.Add(dict.Keys.ElementAt(0), e.Quantity);
                                        dict2.Add(e.Title, statusQuantityDict);
                                    }
                                }
                            }
                            else
                            {
                                Dictionary<string, Dictionary<int, int>> test = new Dictionary<string, Dictionary<int, int>>();
                                Dictionary<int, int> test2 = new Dictionary<int, int>();
                                test2.Add(dict.Keys.ElementAt(0), e.Quantity);
                                test.Add(e.Title, test2);
                                eStatusQuantityList.Add(test);
                            }
                        }
                    }
                }
    
                //ending
                string key = groupedDict.Keys.ElementAt(index);
                final[key] = eStatusQuantityList;
                index++;
                //
            }
            //final contains step3 results
            //Console.WriteLine(final.ToString());
            /*
            for (int i = 0; i<final.Keys.Count; i++)
            {
                Console.WriteLine(final.Keys.ElementAt(i));
            }
    
            for (int i = 0; i < final.Values.Count; i++)
            {
                Console.WriteLine(final.Values.ElementAt(i));
            }
            */
            //
    
            //TimeSpan duration = DateTime.Now - start; //end performance test
            //Console.WriteLine("That took " + duration.TotalMilliseconds + " ms"); //performance test results //60.006 is fine, 600.006 is OOM. //Our range of objects is max. 300 MO's though
    

    正如你所看到的,这是一个功能的地狱。但它的工作正常(2-5毫秒(平均2.5)为我们的最大目标MO)。但是当我们因为某些原因必须重新调整这个功能时,我可以看到人们(除了我自己)搞砸了。因此,可维护性或可读性的任何改进都会很酷。

1 个答案:

答案 0 :(得分:1)

  • LINQ是处理这个问题的更好方法吗?

更好是主观的。更好看?更好的性能?更好(更容易)理解?

  • 性能是否与我的功能相似?

LINQ性能通常不如手动操作那么好,但是总是存在折衷,因为LINQ可以(并不总是)更容易理解。

  • LINQ查询是否更容易理解?

可以。但是,如果您曾经使用过reSharper来查看代码并说它可以将其转换为LINQ查询,那么您就会知道有时它会让它变得不那么容易理解。

  • 是否有另一种处理这种复杂功能的方法 而不是我描述的两种方法?

混合正匹配?您可以手动编写性能关键部分,并将其余部分留在LINQ中。但要找到性能关键部分,您应该使用分析器,而不仅仅是猜测。