简体   繁体   English

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

[英]C# LINQ Group by with the the same amount of items in each group

I cannot figure out how to group items in a correct way like this.我无法弄清楚如何以这样的正确方式对项目进行分组。 For instance we have a list of dates and teams like this:例如,我们有一个日期和团队列表,如下所示:

Date日期 Teams团队 Value价值
1/1/2021 2021 年 1 月 1 日 Team1团队1 10 10
1/1/2021 2021 年 1 月 1 日 Team2团队2 10 10
1/1/2021 2021 年 1 月 1 日 Team3 Team3 10 10
1/2/2021 2021 年 1 月 2 日 Team1团队1 20 20
1/2/2021 2021 年 1 月 2 日 Team2团队2 20 20
1/3/2021 2021 年 1 月 3 日 Team3 Team3 30 30

I want it to be like this:我希望它是这样的:

Date日期 Teams团队 Value价值
1/1/2021 2021 年 1 月 1 日 Team1团队1 10 10
1/1/2021 2021 年 1 月 1 日 Team2团队2 10 10
1/1/2021 2021 年 1 月 1 日 Team3 Team3 10 10
1/2/2021 2021 年 1 月 2 日 Team1团队1 20 20
1/2/2021 2021 年 1 月 2 日 Team2团队2 20 20
1/2/2021 2021 年 1 月 2 日 Team3 Team3 0 0
1/3/2021 2021 年 1 月 3 日 Team1团队1 0 0
1/3/2021 2021 年 1 月 3 日 Team2团队2 0 0
1/3/2021 2021 年 1 月 3 日 Team3 Team3 30 30

In C#:在 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}");
}

Assuming you have it in a database, it may be easier to do it there假设您在数据库中拥有它,那么在那里执行它可能会更容易

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

Assuming your data looks like this:假设您的数据如下所示:

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 }
};

Then this will produce the table you want:然后这将产生你想要的表:

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 };
            });
    });

The first statement gives you all the teams in alphabetical order.第一条语句按字母顺序为您提供所有团队。 The second statement groups the records by date.第二条语句按日期对记录进行分组。 The third statement walks through each date in order, looking up the value for each team on that date (using 0 if there is none).第三个语句按顺序遍历每个日期,查找每个团队在该日期的值(如果没有,则使用 0)。

You can test it like this:你可以像这样测试它:

foreach (var row in table)
{
    Console.WriteLine(row);
}

Output is: 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