c# - 使用 linq 更新对象的性能更好

标签 c# linq performance optimization linq-to-objects

我有两个自定义对象列表,并且想要更新一个列表中所有对象的字段(如果另一个列表中存在与另一对字段匹配的对象)。

这段代码更好地解释了问题并产生了我想要的结果。然而,对于较大的 20k 列表以及包含匹配对象的 20k 列表,这需要相当长的时间(31 秒)。通过使用通用列表 Find(Predicate) 方法,我可以将其改进约 50%。

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
namespace ExperimentFW3
{
    public class PropValue
    {
        public string Name;
        public decimal Val;
        public decimal Total;
    }
    public class Adjustment
    {
        public string PropName;
        public decimal AdjVal;
    }
    class Program
    {
        static List<PropValue> propList;
        static List<Adjustment> adjList;

        public static void Main()
        {
            propList = new List<PropValue>{
                new PropValue{Name = "Alfa", Val=2.1M},
                new PropValue{Name = "Beta", Val=1.0M},
                new PropValue{Name = "Gamma", Val=8.0M}
            };
            adjList = new List<Adjustment>{
                new Adjustment{PropName = "Alfa", AdjVal=-0.1M},
                new Adjustment{PropName = "Beta", AdjVal=3M}
            };

            foreach (var p in propList)
            {
                Adjustment a = adjList.SingleOrDefault(
                    av => av.PropName.Equals(p.Name)
                    );
                if (a != null)
                    p.Total = p.Val + a.AdjVal;
                else
                    p.Total = p.Val;
            }
        }
    }
}

期望的结果是:Alfa总计=2,Beta总计=4,Gamma总计=8

但我想知道是否可以做得更快。即使在结果集中循环超过 20k 项,内部连接两个列表也只需要很少的时间。

var joined = from p in propList
             join a in adjList on p.Name equals a.PropName
             select new { p.Name, p.Val, p.Total, a.AdjVal };

所以我的问题是是否可以像使用 T-SQL 那样做一些事情?对调整值使用 ISNULL(val,0) 从左连接进行更新。

最佳答案

该连接应该相当快,因为​​它将首先循环遍历所有 adjList 以创建查找,然后对于 propList 中的每个元素,它将仅使用查找。这比较大代码中的 O(N * M) 方法更快 - 尽管可以通过调用 ToLookup 轻松解决这个问题(或 ToDictionary,因为您只需要一个值)在循环之前的 adjList 上。

编辑:这是使用ToDictionary修改后的代码。未经测试,请注意...

var adjDictionary = adjList.ToDictionary(av => av.PropName);
foreach (var p in propList)
{
    Adjustment a;
    if (adjDictionary.TryGetValue(p.Name, out a))
    {
        p.Total = p.Val + a.AdjVal;
    }
    else
    {
        p.Total = p.Val;
    }
}

关于c# - 使用 linq 更新对象的性能更好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/271615/

相关文章:

c# - 集合更改时触发事件(添加或删除)

c# - 继承中的逆变

c# - 使用 LINQ,如何根据部分字符串属性过滤集合?

c# - Visual Studio 2015 缺少 XML 注释/文档

android - FragmentStatePagerAdapter 性能问题

c# - 开关盒和泛型检查

c#-如何删除字符串数组中的元音字母?

c# - LINQ 从一个集合中获取不属于另一个集合的元素

python - Pandas 数据帧 : fastest way of updating multiple rows based on a list of dictionaries

php - GROUP BY 和 ORDER BY 太慢了。如何使速度更快?