簡體   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