如何从IGrouping分组结果中获取每组的首个元素?
获取GroupBy分组中的首个元素
嘿,这个需求其实用Linq就能轻松搞定!因为GroupBy返回的每个IGrouping<TKey, TElement>本身就是一个可枚举集合,你只需要对每个分组调用First()(或者FirstOrDefault(),用来处理空分组的极端情况),就能拿到组内的第一个元素。
结合你提供的Extract方法,我们可以直接在分组后的result上链式调用Select来提取目标元素,具体修改后的代码如下:
void Extract() { List<DataHolder> data = new List<DataHolder>(); Random r = new Random(); DateTime d = new DateTime(2019, 9, 19, 7, 0, 0); // 生成测试数据 for (int i = 0; i < 100; i++) { DataHolder dh = new DataHolder(); TimeSpan t = TimeSpan.FromSeconds(r.Next(0, 14400)); dh.OID = i; dh.Value = r.Next(50); dh.Snapshottime = d.Add(t); data.Add(dh); } // 按时间排序数据 List<DataHolder> sortedList = data.OrderBy(o => o.Snapshottime).ToList(); TimeSpan interval = new TimeSpan(0, 15, 0); // 按15分钟间隔分组并按组键排序 var groupedData = sortedList.GroupBy(x => x.Snapshottime.Ticks / interval.Ticks) .OrderBy(x => x.Key); // 提取每个分组的首个元素 var firstElementsPerGroup = groupedData.Select(group => group.First()); // 转换成List方便后续处理(可选) List<DataHolder> firstElementsList = firstElementsPerGroup.ToList(); // 示例:打印验证结果 foreach (var item in firstElementsList) { Console.WriteLine($"OID: {item.OID}, 时间: {item.Snapshottime}, 值: {item.Value}"); } } public class DataHolder { public int OID { get; set; } public double Value { get; set; } public DateTime Snapshottime { get; set; } }
小补充:
First()vsFirstOrDefault():如果能确保每个分组都至少有一个元素(比如你的场景,分组基于非空的已排序列表),用First()就足够;如果存在分组为空的可能性,FirstOrDefault()会返回对应类型的默认值(比如null,因为DataHolder是引用类型),避免抛出异常。- 原代码里
data.OrderBy(o => o.Snapshottime).ToList();这行其实没有生效,因为Linq方法不会修改原集合,只会返回新集合,所以下面重新排序并赋值给sortedList的做法是正确的,不用改动。
内容的提问来源于stack exchange,提问作者Josef
相关产品推荐
相关产品推荐

