[英]C# LINQ Group by with the the same amount of items in each group
我无法弄清楚如何以这样的正确方式对项目进行分组。 例如,我们有一个日期和团队列表,如下所示:
日期 | 团队 | 价值 |
---|---|---|
2021 年 1 月 1 日 | 团队1 | 10 |
2021 年 1 月 1 日 | 团队2 | 10 |
2021 年 1 月 1 日 | Team3 | 10 |
2021 年 1 月 2 日 | 团队1 | 20 |
2021 年 1 月 2 日 | 团队2 | 20 |
2021 年 1 月 3 日 | Team3 | 30 |
我希望它是这样的:
日期 | 团队 | 价值 |
---|---|---|
2021 年 1 月 1 日 | 团队1 | 10 |
2021 年 1 月 1 日 | 团队2 | 10 |
2021 年 1 月 1 日 | Team3 | 10 |
2021 年 1 月 2 日 | 团队1 | 20 |
2021 年 1 月 2 日 | 团队2 | 20 |
2021 年 1 月 2 日 | Team3 | 0 |
2021 年 1 月 3 日 | 团队1 | 0 |
2021 年 1 月 3 日 | 团队2 | 0 |
2021 年 1 月 3 日 | Team3 | 30 |
在 C# 中:
public class DataEntry
{
public string Date;
public string Teams;
public int Value;
}
public static IEnumerable<DataEntry> GetData()
{
var data = new List<DataEntry>()
{
new DataEntry() { Date = "1/1/2021", Teams = "Team1", Value = 10 },
new DataEntry() { Date = "1/1/2021", Teams = "Team2", Value = 10 },
new DataEntry() { Date = "1/1/2021", Teams = "Team3", Value = 10 },
new DataEntry() { Date = "1/2/2021", Teams = "Team1", Value = 20 },
new DataEntry() { Date = "1/2/2021", Teams = "Team2", Value = 20 },
new DataEntry() { Date = "1/3/2021", Teams = "Team3", Value = 30 },
};
var dates = data.Select(d => d.Date).Distinct().OrderBy(d => d);
var teams = data.Select(d => d.Teams).Distinct().OrderBy(d => d);
foreach (var date in dates)
{
foreach (var team in teams)
{
yield return new DataEntry()
{
Date = date,
Teams = team,
Value = data.SingleOrDefault(d => d.Date == date && d.Teams == team)?.Value ?? 0
};
}
}
}
public static void Main(string[] args)
{
foreach (var d in GetData()) Console.WriteLine($"{d.Date} {d.Teams} {d.Value}");
}
假设您在数据库中拥有它,那么在那里执行它可能会更容易
SELECT t.Date, d.Teams, IsNull(tt.Value, 0) as Value
FROM (SELECT DISTINCT Date FROM #Table) t
CROSS JOIN (SELECT DISTINCT Teams FROM #Table) d
LEFT JOIN #Table tt
ON t.Date = tt.Date
AND d.Teams = tt.Teams
ORDER BY t.Date, d.Teams
假设您的数据如下所示:
var data = new[]
{
new { Date = "1/1/2021", Team = "Team1", Value = 10 },
new { Date = "1/1/2021", Team = "Team2", Value = 10 },
new { Date = "1/1/2021", Team = "Team3", Value = 10 },
new { Date = "1/2/2021", Team = "Team1", Value = 20 },
new { Date = "1/2/2021", Team = "Team2", Value = 20 },
new { Date = "1/3/2021", Team = "Team3", Value = 30 }
};
然后这将产生你想要的表:
var teams = data.Select(rec => rec.Team).Distinct().OrderBy(team => team).ToArray();
var groupings = data.GroupBy(rec => DateTime.Parse(rec.Date));
var table = groupings.OrderBy(grouping => grouping.Key).SelectMany(grouping =>
{
var dict = grouping.ToDictionary(rec => rec.Team, rec => rec.Value);
return teams.Select(team =>
{
dict.TryGetValue(team, out int value);
return new { Date = grouping.Key, Team = team, Value = value };
});
});
第一条语句按字母顺序为您提供所有团队。 第二条语句按日期对记录进行分组。 第三个语句按顺序遍历每个日期,查找每个团队在该日期的值(如果没有,则使用 0)。
你可以像这样测试它:
foreach (var row in table)
{
Console.WriteLine(row);
}
Output 是:
{ Date = 1/1/2021 12:00:00 AM, Team = Team1, Value = 10 }
{ Date = 1/1/2021 12:00:00 AM, Team = Team2, Value = 10 }
{ Date = 1/1/2021 12:00:00 AM, Team = Team3, Value = 10 }
{ Date = 1/2/2021 12:00:00 AM, Team = Team1, Value = 20 }
{ Date = 1/2/2021 12:00:00 AM, Team = Team2, Value = 20 }
{ Date = 1/2/2021 12:00:00 AM, Team = Team3, Value = 0 }
{ Date = 1/3/2021 12:00:00 AM, Team = Team1, Value = 0 }
{ Date = 1/3/2021 12:00:00 AM, Team = Team2, Value = 0 }
{ Date = 1/3/2021 12:00:00 AM, Team = Team3, Value = 30 }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.