如何分组列表并拆分每n条记录?

时间:2014-01-22 12:55:52

标签: c# linq

我想知道如何使用LINQ

对项目进行分组并分割每个N记录
# |ITEM  |QUANTITY
==================
1 |ITEM01| 10
2 |ITEM01| 10
3 |ITEM01| 10
.     .     .
.     .     .
22|ITEM01| 10
23|ITEM02| 50
24|ITEM02| 50

假设有一个包含23个ITEM001和2个ITEM002

的列表

如何获得

ITEM  |QUANTITY
=================
ITEM001 | 100
ITEM001 | 100
ITEM001 | 20
ITEM002 | 100

按ITEM分组,如果分组> 10,转到下一个

有没有办法实现它?谢谢你的帮助!

感谢那些好人的帮助!进一步的问题,现在我想将列表分组(每10条记录分组,分组后,如果计数不到10,不要分组),抱歉我的英语不好:(

ITEM  |QUANTITY
=================
ITEM01 | 100
ITEM01 | 100
ITEM01 | 10
ITEM01 | 10
ITEM01 | 10
ITEM02 | 50
ITEM02 | 50

再次感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

var query = 
    items.GroupBy(item => item.Name)
         .SelectMany(g => g.Select((item, index) => new { item, index })
                           .GroupBy(x => x.index / 10)
                           .Select(batch => new Item { 
                                 Name = batch.First().item.Name, 
                                 Quantity = batch.Sum(x => x.item.Quantity) 
                            })).OrderBy(item => item.Name);
  1. 按名称对所有项目进行分组。这将为您提供两组样本数据。
  2. 将每个组拆分为10个项目,并从每个批次中选择新的聚合项目(批次可以包含少于10个项目,作为ITEM001的第三批次)。
  3. 按商品名称订购结果。
  4. 如果您使用MoreLINQ(可从NuGet获得)批量扩展或编写自己的扩展,则可以简化此查询:

    var query = 
        items.GroupBy(item => item.Name)
             .SelectMany(g => g.Batch(10)
                               .Select(batch => new Item { 
                                     Name = batch.First().Name, 
                                     Quantity = batch.Sum(item => item.Quantity) 
                                })).OrderBy(item => item.Name);
    

    假设你有像这样的项目类

    public class Item
    {
        public string Name { get; set; }
        public int Quantity { get; set; }
    }
    

    然后这个项目样本列表(用NBuilder构建):

    var items = Builder<Item>.CreateListOfSize(32)
                             .TheFirst(23)
                                 .With(i => i.Name = "ITEM01")
                                 .And(i => i.Quantity = 10)
                             .TheNext(9)
                                 .With(i => i.Name = "ITEM02")
                                 .And(i => i.Quantity = 50)
                             .Build();
    

    会给出结果:

    [
      { Name: "ITEM01", Quantity: 100 },  
      { Name: "ITEM01", Quantity: 100 },
      { Name: "ITEM01", Quantity: 30  },
      { Name: "ITEM02", Quantity: 450 }
    ]
    

    注意:@Thejaka解决方案在这种情况下将为您提供五个项目 - 将有两个ITEM02项目,数量为350和100。

答案 1 :(得分:0)

注意: 以下答案按项目分组,不计算。不过,我把它留在这里供将来参考。也许有人会有类似的问题。

您可以使用以下LINQ查询来实现它:

List<Item> items = new List<Item>()
{
    new Item() { Name = "Item01", Quantity = 40 }, // 130
    new Item() { Name = "Item01", Quantity = 70 },
    new Item() { Name = "Item01", Quantity = 10 },
    new Item() { Name = "Item01", Quantity = 10 },
    new Item() { Name = "Item02", Quantity = 50 }, // 100
    new Item() { Name = "Item02", Quantity = 50 },
    new Item() { Name = "Item03", Quantity = 10 }  // 10
};

var result =
    // Group by Name, calculate total sum for each group
    items.GroupBy(i => i.Name, (k, v) => new Item()
    {
        Name = k,
        Quantity = v.Sum(i => i.Quantity)
    })
    // Split groups into 100 packages
    .SelectMany(i => Enumerable.Range(0, (int)Math.Ceiling(i.Quantity / 100.0))
                               .Select(n => new Item()
    {
        Name = i.Name,
        Quantity = i.Quantity > ((n + 1) * 100) ? 100 : i.Quantity - n * 100
    }))
    .ToList();

然后列表中有四个元素:

Item01 100
Item01 30
Item02 100
Item03 10