【问题标题】:LINQ Grouping records based on a key and following recordsLINQ 基于键和以下记录对记录进行分组
【发布时间】:2021-07-05 16:56:54
【问题描述】:

我想知道以下是否可以用LINQ实现。此时我按“MeetingType”分组,但结果集不是我想要的,因为我还想根据会议类型的时间顺序保留分组。

所以基本上在下面的示例中,您将看到有 4 个 PoolDiscussion 会议。在这种情况下,我不希望所有 4 条记录在第 3 次和第 4 次会议之间分组讨论 Pool Discussion 发生了另一个不同类型的会议,所以我想要三个组,其中第一个是 PoolDiscussion (有 3 条记录)其次是景观美化(1 条记录),最后是 PoolDiscussion(1 条记录)

假设我有以下数据记录 数据库记录

MeetingName MeetingType MeetingDateTime
With John Pool Discussion 2020-01-02
With Emily Pool Discussion 2020-01-02
With Ed Pool Discussion 2020-01-03
With John Landscaping 2020-01-03
With Ed Pool Discussion 2020-01-04

所以在这种情况下,我要做的是在以下结构中输出 JSON(注意如何有 2 个“PoolDiscussions”分组)

{
    "Meetings": [
        {
            "PoolDiscussion": [
                {
                    "MeetingName": "With John",
                    "MeetingDate": "2020-01-02"
                },
                {
                    "MeetingName": "With Emily",
                    "MeetingDate": "2020-01-02"
                },
                {
                    "MeetingName": "With Ed",
                    "MeetingDate": "2020-01-03"
                }
            ]
        },
        {
            "Landscaping": [
                {
                    "MeetingName": "With John",
                    "MeetingDate": "2020-01-03"
                }
            ]
        },
        {
            "PoolDiscussion": [
                {
                    "MeetingName": "With Ed",
                    "MeetingDate": "2020-01-04"
                }
            ]
        }
    ]
}

【问题讨论】:

标签: c# sql-server linq .net-core


【解决方案1】:

我不认为您可以通过单个 LINQ 查询完全完成您想要的。原因是您没有唯一的分组依据。您基本上是在尝试按会议类型和日期进行分组,因此您可以接近以下内容,但是您将在 3 日的“With Ed”会议上获得额外的“PoolDiscussion”记录...

from meeting in data
group meeting by new { Type = meeting.MeetingType, Date = meeting.MeetingDateTime } into mts
select new { Key = mts.Key.Type, Value = mts.ToList() }).ToList()

这将产生以下内容:

[
        {
            "PoolDiscussion": [
                {
                    "MeetingName": "With John",
                    "MeetingDate": "2020-01-02"
                },
                {
                    "MeetingName": "With Emily",
                    "MeetingDate": "2020-01-02"
                }
             ]
        },
        {  "PoolDiscussion": [
                {
                    "MeetingName": "With Ed",
                    "MeetingDate": "2020-01-03"
                }
            ]
        },
        {
            "Landscaping": [
                {
                    "MeetingName": "With John",
                    "MeetingDate": "2020-01-03"
                }
            ]
        },
        {
            "PoolDiscussion": [
                {
                    "MeetingName": "With Ed",
                    "MeetingDate": "2020-01-04"
                }
            ]
        }
    ]

一旦你有了这个数据集,你就可以遍历它并折叠相邻的“PoolDiscussion”记录

【讨论】:

    【解决方案2】:

    这是一个简单的部分 LINQ 解决方案,但我想知道一种更高效或完全基于 LINQ 的方法:

    var groupedMeetings = new List<KeyValuePair<string, List<Meeting>>>();
    while (meetings.Any())
    {
        var group = meetings.TakeWhile((meeting, index) =>
        {
            return index == 0 || meeting.MeetingType == meetings[index - 1].MeetingType;
        });
        
        groupedMeetings.Add(KeyValuePair.Create(group.First().MeetingType, group.ToList()));
    
        // Skip past the meetings we've already processed.
        meetings = meetings.SkipWhile((meeting, index) =>
        {
            return index == 0 || meeting.MeetingType == meetings[index - 1].MeetingType;
        }).ToList();
    }
    

    这是一种非 LINQ 方法进行比较:

    var groupedMeetings = new List<KeyValuePair<string, List<Meeting>>>();
    
    var i = 0;
    while (i < meetings.Count)
    {
        var meetingType = meetings[i].MeetingType;
    
        // A group will always consist of at least one meeting.
        var group = new List<Meeting>
        {
            meetings[i++]
        };
    
        while (i < meetings.Count - 1 && meetings[i].MeetingType == meetings[i - 1].MeetingType)
        {
            group.Add(meetings[i++]);
        }
    
        groupedMeetings.Add(KeyValuePair.Create(meetingType, group));
    }
    

    这两种方法都假定会议在处理之前已经正确排序,并保留该排序。

    假设以下类:

    public class Meeting
    {
        public string MeetingName { get; set; }
    
        [JsonIgnore]
        public string MeetingType { get; set; }
        
        public DateTime MeetingDate { get; set; }
    }
    

    这个:

    var settings = new JsonSerializerSettings
    {
        Formatting = Formatting.Indented,
        DateFormatString = "yyyy-MM-dd"
    };
    Console.WriteLine(JsonConvert.SerializeObject(groupedMeetings, settings));
    

    生成与您的示例等效的 JSON:

    [
      {
        "Key": "Pool Discussion",
        "Value": [
          {
            "MeetingName": "With John",
            "MeetingDate": "2020-01-02"
          },
          {
            "MeetingName": "With Emily",
            "MeetingDate": "2020-01-02"
          },
          {
            "MeetingName": "With Ed",
            "MeetingDate": "2020-01-03"
          }
        ]
      },
      {
        "Key": "Landscaping",
        "Value": [
          {
            "MeetingName": "With John",
            "MeetingDate": "2020-01-03"
          }
        ]
      },
      {
        "Key": "Pool Discussion",
        "Value": [
          {
            "MeetingName": "With Ed",
            "MeetingDate": "2020-01-04"
          }
        ]
      }
    ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多