gpt4 book ai didi

c# - 复杂的 LINQ 查询与复杂的 for 循环

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:06:47 25 4
gpt4 key购买 nike

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

该函数的目标是创建一个字典(D1),其中Key是一个C(title),Values是另一个字典(D2),其中Key是E(title),Values是另一个字典(D3),其中Key是C(status),value是E(quantity)。所以最后我将拥有所有(唯一的)C(标题),其中我可以看到所有(唯一的)E(标题),其中我可以看到所有不同的 C(状态)和 E(数量)这些状态(作为额外的挑战,如果 2 个 E(数量)在同一类(class)中具有相同的状态和相同的标题,它们应该相互添加,然后作为值输入)。

我让这一切都很好。

但是。该功能庞大且难以理解,因此我正在寻找一种更平易近人的方式来处理这个问题。其中一种方法应该是 LINQ。但是,我对此几乎一无所知,对于一个非常复杂的函数,我几乎无法理解如何在 LINQ 中处理它。我也很关心性能,因为这个 WPF 项目在很大程度上依赖于用户体验。所以我不确定 LINQ 是否真的会让事情变得更快、更慢或相同。

这是你们进来的地方。

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

  • 性能与我的功能相似吗?

  • LINQ 查询是否更易理解?

  • 是否有另一种方法来处理这个复杂的函数
    而不是我描述的 2 种方法?


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

分三步完成:

  1. 第 1 步:循环 MO、C、E 并创建字典列表。

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

  3. 第 3 步:拆分更深层次的词典,以便我们可以按预期使用 E 对象。

结果:已放入'final'对象中。具有作为键 C(title) 和值的字典列表的字典列表。这个字典列表以 E(title) 为键,值为字典。该词典具有键 C(状态)和值 E(数量)。这个E(quantity)是同一个C(status)的每个E的每个quantity对于同一个C的组合值。


        //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 的最大目标)。但我可以看到人们(除了我自己)在出于某种原因不得不重新调整此功能时搞砸了。因此,任何可维护性或可读性方面的改进都会很酷。

最佳答案

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

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

  • 性能与我的功能相似吗?

LINQ 的性能通常不如手动执行,但总要有所取舍,因为 LINQ 可能(并不总是)更容易理解。

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

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

  • 是否有另一种方法来处理这个复杂的函数而不是我正在描述的 2 种方法?

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

关于c# - 复杂的 LINQ 查询与复杂的 for 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22324393/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com