C# 在不影响linq中排序的情况下对已排序列表进行分组

C# 在不影响linq中排序的情况下对已排序列表进行分组,c#,linq,sorting,grouping,C#,Linq,Sorting,Grouping,我有一张物品清单。我需要按一个属性进行排序,然后按一组其他属性对结果进行分组,但这样做只会更改排序并首先维护组。我需要分组,如果需要,同时保持排序。 我试了两种方法 简单排序和分组 model.OrderBy(o=>o.OrderKey).GroupBy(o=>new{o.Key1,o.Key2}) 按顺序列表(PLINQ)排序,然后分组 model.OrderBy(o=>o.OrderKey).AsParallel().AsOrdered().GroupBy(o=>new{o.Key1,o.K

我有一张物品清单。我需要按一个属性进行排序,然后按一组其他属性对结果进行分组,但这样做只会更改排序并首先维护组。我需要分组,如果需要,同时保持排序。 我试了两种方法

  • 简单排序和分组
  • model.OrderBy(o=>o.OrderKey).GroupBy(o=>new{o.Key1,o.Key2})

  • 按顺序列表(PLINQ)排序,然后分组
  • model.OrderBy(o=>o.OrderKey).AsParallel().AsOrdered().GroupBy(o=>new{o.Key1,o.Key2})

    我的意见是

    OrderKey Key1 Key2
    a        1    2
    b        1    2
    c        1    3
    d        1    2
    
    我希望输出像这样

    [
      [a, 1, 2],
      [b, 1, 2]
    ],
    [
     [c, 1, 3]
    ],
    [
     [d, 1, 2]
    ]
    

    这可以通过使用每个项目的索引来解决,并添加一些逻辑来与上一个项目进行比较(除非索引为0):

    //示例数据
    变量列表=新列表{
    新的{orderKey=“a”,key1=1,key2=2},
    新的{orderKey=“b”,key1=1,key2=2},
    新的{orderKey=“c”,key1=1,key2=3},
    新的{orderKey=“d”,key1=1,key2=2}
    };
    var groupNr=0;//初始组
    分类变量=
    列表
    .OrderBy(i=>i.orderKey)
    //为每个项目创建一个新项目,添加一个计算的groupNr:
    .选择((i,nr)=>
    新{
    i、 orderKey,
    i、 关键1,
    i、 关键2,
    groupNr=(nr==0//检查第一组
    ?0//第一组编号必须为0
    :(i.key1==列表[nr-1].key1
    &&i.key2==列表[nr-1].key2)
    ?集团编号
    :++groupNr)
    })
    //现在只需按我们添加的groupNr分组:
    .GroupBy(i=>i.groupNr);
    
    在LINQPad中进行测试会得到以下结果,您应该能够从中提取所需内容:


    [d,1,2]也会在第一组。@UfukHacıoğulları我认为塞雷纳的观点是它不应该在第一组;我认为他想先排序,然后只对紧跟其后的元素进行分组,这就是[c,1,3]将其他两个元素分开的原因。我在谷歌上搜索了这句话:“linq group By Concertive”,并发现了很好的结果-----可能是重复的,还有一种叫做
    groupnexting
    的方法可以做到这一点。
    // Example data
    var list = new List<dynamic>{
                new {orderKey = "a", key1 = 1, key2 = 2},
                new {orderKey = "b", key1 = 1, key2 = 2},
                new {orderKey = "c", key1 = 1, key2 = 3},
                new {orderKey = "d", key1 = 1, key2 = 2}
        };
    
    var groupNr = 0; // initial group
    
    var sorted = 
            list
                .OrderBy(i => i.orderKey)
                // Create a new item for each, adding a calculated groupNr:
                .Select((i, nr) => 
                           new { 
                                i.orderKey, 
                                i.key1, 
                                i.key2, 
                                groupNr = (nr == 0 // check if first group
                                               ? 0 // first groupNr must be 0
                                               : (i.key1 == list[nr-1].key1 
                                                    && i.key2 == list[nr-1].key2) 
                                                  ? groupNr 
                                                  : ++groupNr ) 
            })
    
         // Now just group by the groupNr we have added:
     .GroupBy(i => i.groupNr);