对于性能调整,请使用 HashSet 而不是 List。
我也可以推荐 ISBN:0321637003(LINQ to Objects),也许有更新版本。但无论如何它仍然是非常好的内容。
如果您的 dict 中有数百万个条目,您可以尝试 PLINQ。
return base.Values.Single(x => x.ContainsKey(productId))[productId];
示例 json 抛出异常,因为您的 productId (P1, P2) 不是唯一的且 P5 不存在。
如果我寻找 productId "P5" 我想得到...
[{“字段”:“V5”}]
没有P5
我不确定它是否有帮助,但这是我的示例代码。我已将您的 json 放入一个文件并对其进行反序列化。
var lFile = new FileInfo(@"C:\_test\data.json");
using var lReader = lFile.OpenText();
var lJsonStr = lReader.ReadToEnd();
var lDicDic = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, List<ProductId>>>>(lJsonStr);
//var lTest1 = lDicDic.Values.Single(x => x.ContainsKey("P1"))["P1"]; //Not working, P1 is not unique!
var lTest2 = lDicDic["O2"]["P1"];
//contains => "Field": "V3" + "Field": "V5"
var lTest3 = lDicDic
.SelectMany(p => p.Value.Values.SelectMany(qItem => qItem))
.FirstOrDefault(qProducts => qProducts.Field == "V5");
//contains => "Field": "V5"
var lTest4 = lDicDic["O2"]["P1"].Last();
//contains => "Field": "V5"
编辑:
在您的 Fiddler 代码之后,我能够对其进行测试。
public List<MyTask> GetByProductId(string productId)
{
var lProductDict = Tasks.Values.SingleOrDefault(x => x.ContainsKey(productId));
return lProductDict?.GetValueOrDefault(productId);
}
我的胃告诉我,你目前的方法很难改进;)
如果您对这个嵌套的 dict 有很多调用,并且它的变化不是很频繁,那么在开始处理时将 dict 从 TopDown 重构为 BottomUp 可能是有意义的。
无论如何,如果我的 cmets 有帮助,请点赞我的回答 :)
如果我是你,我会用真实数据制作一些测试用例。
不要忘记:如果您处于调试模式,请在项目中启用“优化代码”。在我的测试用例中,没有优化代码的 AVG 为 47ms,优化代码为 42ms:
你可以试试 PLINQ:
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/introduction-to-plinq
这是我的测试场景:
var lStopWatch = new Stopwatch();
lStopWatch.Restart();
var lJobs = new Jobs("F1");
const int TestOrderCount = 1000000;
const int TestAvgCount = 1000;
for (var lIndex = 1; lIndex < TestOrderCount; lIndex++)
{
var lNoStr = lIndex.ToString("D6");
lJobs.Add($"O{lNoStr}", $"P{lNoStr}", $"V{lNoStr}");
}
var GetTimes = new List<long>();
var lRandom = new Random();
var lTestCases = Enumerable
.Range(1, TestAvgCount - 1)
.Select(r => $"P{lRandom.Next(1, TestOrderCount - 1):D6}")
.ToList();
var lSetupTimeMs = lStopWatch.ElapsedMilliseconds;
Debug.WriteLine($"SetupTimeMs: {lSetupTimeMs}");
foreach (var lTestCase in lTestCases)
{
lStopWatch.Restart();
var lTest = lJobs.GetByProductId(lTestCase);
GetTimes.Add(lStopWatch.ElapsedMilliseconds);
}
var lAvg = GetTimes.Sum() / TestAvgCount; //AVG Ms per get
Debug.WriteLine($"AVG: {lAvg}");