现在我有这个复杂的函数,我有一个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步:循环MO,C,E,并创建一个词典列表。
步骤2:加入步骤1结果的重复键,然后创建一个 第一阶段词典。
结果:已经进入了#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)。但是当我们因为某些原因必须重新调整这个功能时,我可以看到人们(除了我自己)搞砸了。因此,可维护性或可读性的任何改进都会很酷。
答案 0 :(得分:1)
更好是主观的。更好看?更好的性能?更好(更容易)理解?
LINQ性能通常不如手动操作那么好,但是总是存在折衷,因为LINQ可以(并不总是)更容易理解。
可以。但是,如果您曾经使用过reSharper来查看代码并说它可以将其转换为LINQ查询,那么您就会知道有时它会让它变得不那么容易理解。
混合正匹配?您可以手动编写性能关键部分,并将其余部分留在LINQ中。但要找到性能关键部分,您应该使用分析器,而不仅仅是猜测。