如何离开连接字符串列表并用零填充缺失值

时间:2018-12-31 20:41:23

标签: c# linq

我有以下带有测试数据的示例:

class Program
{
    private class Item
    {
        public int Id { get; set; }
        public DateTime CreatedDate { get; set; }
        public string Type { get; set; }
    }

    static void Main(string[] args)
    {
        List<string> types = new List<string>{ "TypeA", "TypeB", "TypeC" };

        List<Item> data = new List<Item>
        {
            new Item { Id = 1, CreatedDate = DateTime.Parse("01/01/2017"), Type = "TypeA" },
            new Item { Id = 2, CreatedDate = DateTime.Parse("01/01/2017"), Type = "TypeB" },
            new Item { Id = 3, CreatedDate = DateTime.Parse("01/02/2017"), Type = "TypeA" },
            new Item { Id = 4, CreatedDate = DateTime.Parse("01/02/2017"), Type = "TypeB" },
            new Item { Id = 5, CreatedDate = DateTime.Parse("01/03/2017"), Type = "TypeA" },
            new Item { Id = 6, CreatedDate = DateTime.Parse("01/03/2017"), Type = "TypeB" },
            new Item { Id = 7, CreatedDate = DateTime.Parse("01/04/2017"), Type = "TypeA" },
            new Item { Id = 8, CreatedDate = DateTime.Parse("01/04/2017"), Type = "TypeB" },
            new Item { Id = 9, CreatedDate = DateTime.Parse("01/05/2017"), Type = "TypeA" },
            new Item { Id = 10, CreatedDate = DateTime.Parse("01/05/2017"), Type = "TypeB" },

            new Item { Id = 11, CreatedDate = DateTime.Parse("02/01/2017"), Type = "TypeA" },
            new Item { Id = 12, CreatedDate = DateTime.Parse("02/01/2017"), Type = "TypeB" },
            new Item { Id = 13, CreatedDate = DateTime.Parse("02/01/2017"), Type = "TypeC" },
            new Item { Id = 14, CreatedDate = DateTime.Parse("02/02/2017"), Type = "TypeA" },
            new Item { Id = 15, CreatedDate = DateTime.Parse("02/02/2017"), Type = "TypeB" },
            new Item { Id = 16, CreatedDate = DateTime.Parse("02/02/2017"), Type = "TypeC" },
            new Item { Id = 17, CreatedDate = DateTime.Parse("02/03/2017"), Type = "TypeA" },
            new Item { Id = 18, CreatedDate = DateTime.Parse("02/03/2017"), Type = "TypeB" },
            new Item { Id = 19, CreatedDate = DateTime.Parse("02/03/2017"), Type = "TypeC" },
            new Item { Id = 20, CreatedDate = DateTime.Parse("02/05/2017"), Type = "TypeB" },
            new Item { Id = 21, CreatedDate = DateTime.Parse("02/05/2017"), Type = "TypeC" },

            new Item { Id = 22, CreatedDate = DateTime.Parse("03/01/2017"), Type = "TypeC" },
            new Item { Id = 23, CreatedDate = DateTime.Parse("03/01/2017"), Type = "TypeB" },
            new Item { Id = 24, CreatedDate = DateTime.Parse("03/01/2017"), Type = "TypeC" },
            new Item { Id = 25, CreatedDate = DateTime.Parse("03/02/2017"), Type = "TypeA" },
            new Item { Id = 26, CreatedDate = DateTime.Parse("03/02/2017"), Type = "TypeB" },
            new Item { Id = 27, CreatedDate = DateTime.Parse("03/02/2017"), Type = "TypeC" },
            new Item { Id = 28, CreatedDate = DateTime.Parse("03/03/2017"), Type = "TypeB" },
            new Item { Id = 29, CreatedDate = DateTime.Parse("03/03/2017"), Type = "TypeB" },
            new Item { Id = 30, CreatedDate = DateTime.Parse("03/03/2017"), Type = "TypeC" },
            new Item { Id = 31, CreatedDate = DateTime.Parse("03/05/2017"), Type = "TypeB" },
            new Item { Id = 32, CreatedDate = DateTime.Parse("03/05/2017"), Type = "TypeC" },
        };

        var result = data
            .GroupBy(d => new
            {
                d.Type,
                d.CreatedDate.Year,
                d.CreatedDate.Month
            })
            .Select(i => new
            {
                Month = new DateTime(i.Key.Year, i.Key.Month, 1),
                i.Key.Type,
                Count = i.Count()
            })
            .OrderBy(o=>o.Month)
            .ThenBy(o=>o.Type);

        foreach (var r in result)
        {
            Console.WriteLine("{0} - {1}: {2}", r.Month, r.Type, r.Count);
        }

        Console.ReadKey();
    }
}

结果:

  

2017-01-01 12:00:00 AM-TypeA:5

     

2017-01-01 12:00:00 AM-TypeB:5

     

2017-02-01 12:00:00 AM-TypeA:3

     

2017-02-01 12:00:00 AM-B型:4

     

2017-02-01 12:00:00 AM-TypeC:4

     

2017-03-01 12:00:00 AM-TypeA:1

     

2017-03-01 12:00:00 AM-TypeB:5

     

2017-03-01 12:00:00 AM-TypeC:5

但是我坚持要使用

List<string> types 

所以我可以得到以下结果:

  

2017-01-01 12:00:00 AM-TypeA:5

     

2017-01-01 12:00:00 AM-TypeB:5

     

2017-01-01 12:00:00 AM-TypeC:0

     

2017-02-01 12:00:00 AM-TypeA:3

     

2017-02-01 12:00:00 AM-B型:4

     

2017-02-01 12:00:00 AM-TypeC:4

     

2017-03-01 12:00:00 AM-TypeA:1

     

2017-03-01 12:00:00 AM-TypeB:5

     

2017-03-01 12:00:00 AM-TypeC:5

我希望每个月都具有所有类型(在这种情况下为3),所有缺少的类型默认为零。

1 个答案:

答案 0 :(得分:2)

正如jdweng在评论中提到的那样,要加入Join,您需要创建一个模板列表。因此,恕我直言,在这种特殊情况下,一种更简单的解决方法是完全省略Join并填写缺失的数据。

var result = data
            .GroupBy(d => new
            {
                d.Type,
                d.CreatedDate.Year,
                d.CreatedDate.Month
            })
            .Select(i => new
            {
                Month = new DateTime(i.Key.Year, i.Key.Month, 1),
                i.Key.Type,
                Count = i.Count()
            })
            .ToList();


        var dateList = result.Select(x=>x.Month).Distinct().ToList();
        void GenerateEmptyEntries()
        {
            foreach(var date in dateList)
            {
                foreach(var type in types)
                {
                    if(!result.Any(x=>x.Month == date && x.Type == type))
                    {
                        result.Add(new {Month = date, Type = type, Count = 0});
                    }
                }
            }
        }

        GenerateEmptyEntries();
        foreach (var r in result.OrderBy(o=>o.Month)
            .ThenBy(o=>o.Type))
        {
            Console.WriteLine("{0} - {1}: {2}", r.Month, r.Type, r.Count);
        }

输出

01-01-2017 00:00:00 - TypeA: 5
01-01-2017 00:00:00 - TypeB: 5
01-01-2017 00:00:00 - TypeC: 0
01-02-2017 00:00:00 - TypeA: 3
01-02-2017 00:00:00 - TypeB: 4
01-02-2017 00:00:00 - TypeC: 4
01-03-2017 00:00:00 - TypeA: 1
01-03-2017 00:00:00 - TypeB: 5
01-03-2017 00:00:00 - TypeC: 5