我有以下带有测试数据的示例:
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),所有缺少的类型默认为零。
答案 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