繁体   English   中英

C# LINQ 分组,每组物品数量相同

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM