需要将 LINQ(GROUP BY 和 SUM ) 转换为 foreach 逻辑.C#.



我必须根据 3 个键值对某些记录进行分组,然后将其他值汇总到一个组中。但后来意识到 LINQ 的性能不如每个 .所以请帮助将每个 linq 代码转换为正常代码

    List<Test> testList= new List<Test>();
    testList.GroupBy(ab => new
    {
     ab.Property1,
     ab.Property2,
     ab.Property3                         
    }).Select(a => new Test
            {
             Property1= a.Key.Property1,
             Property2= a.Key.Property2,
             Property3= a.Key.Property3,               
             Property4= a.Select(ab => ab.Property4).FirstOrDefault(),
             Property5= a.Sum(ab => ab.Property5),
             Property6= a.Sum(ab => ab.Property6),
             Property7= a.Sum(ab => ab.Property7),
             Property8= a.Sum(ab => ab.Property8),
            });

尝试以下链接进行转换。 http://www.sqltolinq.com/

更新

您也可以根据以下链接使用锐化器。如何让 Resharper 转换回 foreach 循环

一行一行应该是:

List<Test> testList = new List<Test>();
// string, string, string = Property1, Property2, Property3
var dict = new Dictionary<Tuple<string, string, string>, List<Test>>();
foreach (var el in testList)
{
    List<Test> list;
    var key = Tuple.Create(el.Property1, el.Property2, el.Property3);
    if (!dict.TryGetValue(key, out list))
    {
        list = new List<Test>();
        dict.Add(key, list);
    }
    list.Add(el);
}
var output = new List<Test>(dict.Count);
foreach (var kv in dict)
{
    var list = kv.Value;
    var el = new Test
    {
        Property1 = kv.Key.Item1,
        Property2 = kv.Key.Item2,
        Property3 = kv.Key.Item3,
        Property4 = list[0].Property4,
    };
    output.Add(el);
    for (int i = 0; i < list.Count; i++)
    {
        el.Property5 += list[i].Property5;
        el.Property6 += list[i].Property6;
        el.Property7 += list[i].Property7;
        el.Property8 += list[i].Property8;
    }
}

这里唯一"真正的"优势是Sum部分的内部for循环是单个for,而不是四个独立Sum使用的四个独立for

但是还有另一种方法可以做到这一点,它与 LINQ 不同...

List<Test> testList = new List<Test>();
// string, string, string = Property1, Property2, Property3
var dict = new Dictionary<Tuple<string, string, string>, Test>();
foreach (var el in testList)
{
    Test el2;
    var key = Tuple.Create(el.Property1, el.Property2, el.Property3);
    if (!dict.TryGetValue(key, out el2))
    {
        el2 = new Test
        {
            Property1 = el.Property1,
            Property2 = el.Property2,
            Property3 = el.Property3,
            Property4 = el.Property4,
        };
        dict.Add(key, el2);
    }
    el2.Property5 += el.Property5;
    el2.Property6 += el.Property6;
    el2.Property7 += el.Property7;
    el2.Property8 += el.Property8;
}
var output = dict.Values.ToList();

在这里,我们统一了两个foreach循环,并删除了内部for循环。

现在,除非您正在处理数百万条记录,否则我认为这两种解决方案的差异不会太大。

请注意,我的代码和 LINQ 代码之间的输出存在重要差异:GroupBy运算符在IEnumerable上使用时,保证组的顺序与输入中的顺序相同(因此第一个元素将生成第一个组,下一个具有不同键的元素将生成第二个组,依此类推(。使用Dictionary<,>这不会发生。输出的顺序未定义,并且是"随机的"。

最新更新