C#LINQ-对字典进行排序和分组<;字符串,日期时间>;按最大组大小的日期

C#LINQ-对字典进行排序和分组<;字符串,日期时间>;按最大组大小的日期,linq,datetime,sorting,group-by,Linq,Datetime,Sorting,Group By,我希望从字典中创建批,并具有以下约束: 批处理中的所有项目共享相同的日期 单个批次中最多只能有X个项目。如果有多个项目的日期相同,则必须创建另一批 我已经计算出了以下逻辑,但我想知道是否有其他更简洁的方法来处理linq using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace dictionary_sort_by_value_test { class P

我希望从
字典
中创建批,并具有以下约束:

  • 批处理中的所有项目共享相同的日期
  • 单个批次中最多只能有X个项目。如果有多个项目的日期相同,则必须创建另一批 我已经计算出了以下逻辑,但我想知道是否有其他更简洁的方法来处理linq

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace dictionary_sort_by_value_test
    {
        class Program
        {
            static void Main(string[] args)
            {
                int maxBatchSize = 3;
    
                Dictionary<string, DateTime> secs = new Dictionary<string, DateTime>();
                secs.Add("6571 JT", new DateTime(2011, 1, 10));
                secs.Add("6572 JT", new DateTime(2011, 1, 12));
                secs.Add("6573 JT", new DateTime(2011, 1, 12));
                secs.Add("6574 JT", new DateTime(2011, 1, 12));
                secs.Add("6575 JT", new DateTime(2011, 1, 10));
                secs.Add("6576 JT", new DateTime(2011, 1, 11));
                secs.Add("6577 JT", new DateTime(2011, 1, 11));
                secs.Add("6578 JT", new DateTime(2011, 1, 11));
                secs.Add("6579 JT", new DateTime(2011, 1, 11));
    
                var sorted = secs.OrderBy(o => o.Value).GroupBy(o => o.Value);
    
                foreach (var date in sorted)
                {    
                    Console.Write("\nNew batch at {0} \n", date.Key);
                    int batchsize = 0;
                    foreach (var sec in date)
                    {
                        if (batchsize < maxBatchSize)
                        {
                            Console.Write("  {0} {1} \n", sec.Key, sec.Value);
                            batchsize++;
                        }
                        else
                        {
                            Console.Write("\nNew batch at {0} \n", date.Key);
                            Console.Write("  {0} {1} \n", sec.Key, sec.Value);
                            batchsize = 1;
                        }
                    }
                }
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用System.Linq;
    使用系统文本;
    名称空间字典\u按值排序\u测试
    {
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    int maxBatchSize=3;
    Dictionary secs=新字典();
    第二节添加(“6571 JT”,新日期时间(2011年1月10日));
    第二节添加(“6572 JT”,新日期时间(2011年1月12日));
    第二节添加(“6573 JT”,新日期时间(2011年1月12日));
    第二节添加(“6574 JT”,新日期时间(2011年1月12日));
    第二节添加(“6575 JT”,新日期时间(2011年1月10日));
    第二节添加(“6576 JT”,新日期时间(2011年1月11日));
    第二节添加(“6577 JT”,新日期时间(2011年1月11日));
    第二节添加(“6578 JT”,新日期时间(2011年1月11日));
    第二节添加(“6579 JT”,新日期时间(2011年1月11日));
    var sorted=secs.OrderBy(o=>o.Value).GroupBy(o=>o.Value);
    foreach(已排序的var日期)
    {    
    Write(“\n在{0}\n处的新批处理,date.Key”);
    int batchsize=0;
    foreach(var秒输入日期)
    {
    if(batchsize
    不是严格使用linq来解决问题,而是一种更简洁的迭代处理方式:

    static void Main(string[] args)
    {
        int maxBatchSize = 3;
    
        Dictionary<string, DateTime> secs = new Dictionary<string, DateTime>();
        secs.Add("6571 JT", new DateTime(2011, 1, 10));
        secs.Add("6572 JT", new DateTime(2011, 1, 12));
        secs.Add("6573 JT", new DateTime(2011, 1, 12));
        secs.Add("6574 JT", new DateTime(2011, 1, 12));
        secs.Add("6575 JT", new DateTime(2011, 1, 10));
        secs.Add("6576 JT", new DateTime(2011, 1, 11));
        secs.Add("6577 JT", new DateTime(2011, 1, 11));
        secs.Add("6578 JT", new DateTime(2011, 1, 11));
        secs.Add("6574 JT", new DateTime(2011, 1, 11));
        secs.Add("6579 JT", new DateTime(2011, 1, 11));
        secs.Add("6580 JT", new DateTime(2011, 1, 11));
        secs.Add("6581 JT", new DateTime(2011, 1, 11));
        secs.Add("6582 JT", new DateTime(2011, 1, 11));
        secs.Add("6583 JT", new DateTime(2011, 1, 11));
    
        secs.OrderBy(o => o.Value).GroupBy(o => o.Value).ToList().ForEach(date =>
                       {
                           Console.Write("\nNew batch at {0} \n", date.Key);
                           int batchsize = 0;
                           foreach (var sec in date)
                           {
                               if (batchsize >= maxBatchSize)
                               {
                                   Console.Write("\nNew batch at {0} \n", date.Key);
                                   batchsize = 0;
                               }
    
                               Console.Write("  {0} {1} \n", sec.Key, sec.Value);
                               batchsize++;
                           }
                       });
    
        Console.ReadLine();
    }
    
    static void Main(字符串[]args)
    {
    int maxBatchSize=3;
    Dictionary secs=新字典();
    第二节添加(“6571 JT”,新日期时间(2011年1月10日));
    第二节添加(“6572 JT”,新日期时间(2011年1月12日));
    第二节添加(“6573 JT”,新日期时间(2011年1月12日));
    第二节添加(“6574 JT”,新日期时间(2011年1月12日));
    第二节添加(“6575 JT”,新日期时间(2011年1月10日));
    第二节添加(“6576 JT”,新日期时间(2011年1月11日));
    第二节添加(“6577 JT”,新日期时间(2011年1月11日));
    第二节添加(“6578 JT”,新日期时间(2011年1月11日));
    第二节添加(“6574 JT”,新日期时间(2011年1月11日));
    第二节添加(“6579 JT”,新日期时间(2011年1月11日));
    第二节添加(“6580 JT”,新日期时间(2011年1月11日));
    第二节添加(“6581 JT”,新日期时间(2011年1月11日));
    第二节添加(“6582 JT”,新日期时间(2011年1月11日));
    第二节添加(“6583 JT”,新日期时间(2011年1月11日));
    secs.OrderBy(o=>o.Value).GroupBy(o=>o.Value).ToList().ForEach(日期=>
    {
    Write(“\n在{0}\n处的新批处理,date.Key”);
    int batchsize=0;
    foreach(var秒输入日期)
    {
    如果(batchsize>=maxBatchSize)
    {
    Write(“\n在{0}\n处的新批处理,date.Key”);
    batchsize=0;
    }
    写入(“{0}{1}\n”,秒键,秒值);
    batchsize++;
    }
    });
    Console.ReadLine();
    }
    
    您可以使用2个GroupBys来完成。首先按日期时间分组,然后按页面分组。我必须显式地指定泛型参数,因为编译器选择了错误的重载,这使得查询代码更长

    var groups = secs.GroupBy<KeyValuePair<string, DateTime>, DateTime, string, Group>(
        p => p.Value,
        p => p.Key,
        (d, g) => new Group {
            Date = d,
            Pages = g.Select((s, i) => new KeyValuePair<string, int>(s, i / maxBatchSize))
                .GroupBy<KeyValuePair<string, int>, int, string, Page>(
                    p => p.Value,
                    p => p.Key,
                    (p, g2) => new Page { Id = p, Items = g2.ToList() }) });
    
    foreach (var group in groups)
    {
        Console.WriteLine("Date: {0}", group.Date);
        foreach (var page in group.Pages)
        {
            Console.WriteLine("Page: {0}", page.Id);
            foreach (var key in page.Items)
                Console.WriteLine(key);
        }
    }
    
    var groups=secs.GroupBy(
    p=>p.值,
    p=>p.键,
    (d,g)=>新组{
    日期=d,
    Pages=g.Select((s,i)=>newkeyvaluepair(s,i/maxBatchSize))
    .群比(
    p=>p.值,
    p=>p.键,
    (p,g2)=>新页面{Id=p,Items=g2.ToList()});
    foreach(组中的var组)
    {
    WriteLine(“日期:{0}”,group.Date);
    foreach(group.Pages中的变量页)
    {
    WriteLine(“Page:{0}”,Page.Id);
    foreach(page.Items中的var键)
    控制台。写入线(键);
    }
    }
    
    如您所见,我必须定义2个类,因为正如我所说,我必须指定泛型参数,因为使用匿名类型使重载解析选择另一个重载

    class Group
    {
        public DateTime Date;
        public IEnumerable<Page> Pages;
    }
    
    class Page
    {
        public int Id;
        public IEnumerable<string> Items;
    }
    
    类组
    {
    公共日期时间日期;
    公共可数页;
    }
    类页
    {
    公共int Id;
    公共物品;
    }
    

    希望这有帮助。

    您可以按键分组,然后在结果中按项目索引除以所需的块大小进行分组

    var chunkSize = 3;
    var sorted = secs
        .OrderBy(kv => kv.Key)
        .GroupBy(o => o.Value)
        .Select(g => new {Chunks = g.Select((o,i) => new {Val = o, Index = i})
                                    .GroupBy(item => item.Index / chunkSize)});
    
    并显示:

     foreach(var item in sorted.SelectMany(item => item.Chunks))
     {
         Console.WriteLine("New batch at " + item.First().Val.Value);
         foreach(var element in item)
             Console.WriteLine(element.Val.Key);
    }
    

    我也看不到您在代码中在何处/如何创建新批处理。您正在计算批次数,但不是每个批次都在创建新批次并将其添加到“结果”中。就我个人而言,你唯一能用LINQ做到这一点的方法就是再打一个平局,这样你也可以按这个分组。或者将逻辑实现为IEnumerable上的扩展方法。这样,它看起来像LINQ,感觉像LINQ,而且它将是LINQ,因为这就是LINQ的实现方式。谢谢。这正是我想要的。看起来不太好看,但我喜欢它,而且很管用。