如何在C#中按规则过滤List/Array记录并保留最高时间条目?
C# 基于Lambda与HashSet的双向消息筛选实现
需求说明
需要对C#的List/Array中的消息记录按以下规则过滤:
- 核心发送方固定为1,需处理其与多个接收方的双向/单向记录
- 规则1:若存在「发送方1→接收方X」和「发送方X→接收方1」的双向记录,需纳入筛选范围;仅存在单向记录(如1→3无反向)时,也保留该单向记录
- 规则2:从筛选结果中,为每个与1交互的对方ID保留时间戳最高的单条记录,包含Sender、Receiver、Time、Val字段
- 优先使用Lambda表达式结合HashSet实现
输入输出示例
输入数据
"secrets": [ { "sender": 1, "receiver": 2, "time": 2000, "val": "This is Val1" }, { "sender": 2, "receiver": 1, "time": 2100, "val": "This is Val2" }, { "sender": 1, "receiver": 2, "time": 1500, "val": "This is Val3" }, { "sender": 1, "receiver": 3, "time": 2500, "val": "This is Val4" } ]
预期输出
"outcome": [ { "sender": 2, "receiver": 1, "time": 2100, "val": "This is Val2" }, { "sender": 1, "receiver": 3, "time": 2500, "val": "This is Val4" } ]
尝试的错误代码
int senderId = 1; for(int i=0; i<receivers; i++) { var senderSecrets = secrets.Where(x => (x.sender == senderId) && (x.receiver == receivers[i])).ToArray(); var receiverSecrets = secrets.Where(x => (x.sender == receivers[i]) && (x.receiver == senderId)).ToArray(); // 后续逻辑缺失,且循环遍历方式效率低下 }
正确实现方案
完整代码
using System; using System.Collections.Generic; using System.Linq; // 消息实体类 public class Secret { public int sender { get; set; } public int receiver { get; set; } public int time { get; set; } public string val { get; set; } } public class Program { public static void Main() { List<Secret> secrets = new List<Secret> { new Secret { sender = 1, receiver = 2, time = 2000, val = "This is Val1" }, new Secret { sender = 2, receiver = 1, time = 2100, val = "This is Val2" }, new Secret { sender = 1, receiver = 2, time = 1500, val = "This is Val3" }, new Secret { sender = 1, receiver = 3, time = 2500, val = "This is Val4" } }; int targetSender = 1; // 筛选所有与目标发送方相关的记录 var relatedSecrets = secrets.Where(s => s.sender == targetSender || s.receiver == targetSender); // 用HashSet快速获取所有交互的对方ID(自动去重) var partnerIds = new HashSet<int>(relatedSecrets.Select(s => s.sender == targetSender ? s.receiver : s.sender)); // 按对方ID分组,每组取时间戳最大的记录 var result = partnerIds.Select(partnerId => relatedSecrets.Where(s => (s.sender == targetSender && s.receiver == partnerId) || (s.sender == partnerId && s.receiver == targetSender)) .OrderByDescending(s => s.time) .First()) .ToList(); // 输出验证 foreach (var item in result) { Console.WriteLine($"sender: {item.sender}, receiver: {item.receiver}, time: {item.time}, val: {item.val}"); } } }
代码说明
- HashSet的作用:快速去重获取所有与1交互的伙伴ID,避免重复处理同一接收方,提升效率
- 核心逻辑:对每个伙伴ID,筛选出所有双向/单向交互记录,通过
OrderByDescending+First直接提取时间戳最高的记录 - 效率优化:全程使用Linq链式调用结合HashSet,避免低效的循环遍历,时间复杂度更优
内容的提问来源于stack exchange,提问作者David Jackson
相关产品推荐
相关产品推荐

