c# - 加快迭代两个 foreach 循环

标签 c# performance linq foreach

尝试通过两个 foreach 循环加快迭代速度,目前大约需要 15 秒`

foreach (var prodCost in Settings.ProdCostsAndQtys)
{
    foreach (var simplified in Settings.SimplifiedPricing
        .Where(simplified => prodCost.improd.Equals(simplified.PPPROD) && 
               prodCost.pplist.Equals(simplified.PPLIST)))
    {
        prodCost.pricecur = simplified.PPP01;
        prodCost.priceeur = simplified.PPP01;
    }
}

基本上是 ProdCostsAndQtys list 是具有 5 个属性的对象列表,列表大小为 798677
SimplifiedPricing list 是具有 44 个属性的对象列表,此列表的大小为 347,但很可能会变得更大(因此现在想要获得最佳性能)。

如果两个条件匹配,则循环遍历第二个循环内第一个列表中的所有对象,它们将第一个循环中的两个属性替换为第二个循环。

最佳答案

看来你的SimplifiedPricing是一个较小的查找列表,外部循环在一个较大的列表上迭代。在我看来,延迟的主要来源似乎是对较小列表中的每个项目进行 Equals 检查以匹配较大列表中的每个项目。此外,当您有匹配项时,您会更新较大列表中的值,因此多次更新看起来是多余的。

考虑到这一点,我建议建立一个 Dictionary对于较小列表中的项目,会增加内存消耗,但会大大加快查找时间。首先我们需要一些东西来保存这个字典的键。我假设 improdpplist是整数,但在这种情况下并不重要:

public struct MyKey
{
    public readonly int Improd;
    public readonly int Pplist;

    public MyKey(int improd, int pplist)
    {
        Improd = improd;
        Pplist = pplist;
    }

    public override int GetHashCode()
    {
        return Improd.GetHashCode() ^ Pplist.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        if (!(obj is MyKey)) return false;

        var other = (MyKey)obj;
        return other.Improd.Equals(this.Improd) && other.Pplist.Equals(this.Pplist);
    }
}

现在我们有了可以一次性比较 Pplist 和 Improd 的东西,我们可以将它用作包含 SimplifiedPricing 的字典的键。 .
IReadOnlyDictionary<MyKey, SimplifiedPricing> simplifiedPricingLookup =
    (from sp in Settings.SimplifiedPricing
     group sp by new MyKey(sp.PPPROD, sp.PPLIST) into g
     select new {key = g.Key, value = g.Last()}).ToDictionary(o => o.key, o => o.value);

注意 IReadOnlyDictionary .这是为了表明我们在创建此字典后不修改它的意图,从而使我们能够安全地并行化主循环:
Parallel.ForEach(Settings.ProdCostsAndQtys, c =>
{
    SimplifiedPricing value;
    if (simplifiedPricingLookup.TryGetValue(new MyKey(c.improd, c.pplist), out value))
    {
        c.pricecur = value.PPP01;
        c.priceeur = value.PPP01;
    }
});

这应该会改变你的单线程 O(n²)循环到并行化 O(n)循环,创建 simplifiedPricingLookup 的开销很小字典。

关于c# - 加快迭代两个 foreach 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25568500/

相关文章:

c# - 如何通过 FormUrlEncodedContent 传递 List<int>

c# - Visual Studio 任务窗口 - 等待与阻止的任务

c# - 软件支持系统的唯一票号

c# - 忽略一项的嵌套列表的自动映射器

c# - Array.Count() 比 List.Count() 慢得多

database - 反规范化以何种方式提高数据库性能?

c# - 哪种模式更适合 SqlConnection 对象?

c# - 使用数据注释的 WPF MVVM 验证

c# - 比较两个 LINQ 查询,其中语句 Hasvalue 与 !=null

c# - C# XMlSerializer 中具有特殊字符的 XML 反序列化