如何使用LINQ实现双层分组?按真值表/函数行为分组
用LINQ实现布尔操作符的真值表分组
要实现真值表一致的操作符分组,核心思路是先按操作符聚合完整真值表,再根据真值表内容生成唯一标识进行二次分组,以下是具体实现方案:
1. 核心逻辑拆解
- 第一步:将原始
Row集合按OperatorName分组,得到每个操作符对应的完整真值表条目。 - 第二步:为每个操作符的真值表生成唯一"特征键"(确保真值表内容完全一致的操作符拥有相同键)。
- 第三步:按"特征键"分组,将真值表一致的操作符归为同一组。
2. 代码实现示例
定义Row类型
public record Row(bool? Left, string OperatorName, bool? Right, bool? Result);
示例数据
var rows = new List<Row> { // xor的真值表 new Row(true, "xor", true, false), new Row(true, "xor", false, true), new Row(false, "xor", true, true), new Row(false, "xor", false, false), // 与xor行为一致的xor_ new Row(true, "xor_", true, false), new Row(true, "xor_", false, true), new Row(false, "xor_", true, true), new Row(false, "xor_", false, false), // and的真值表 new Row(true, "and", true, true), new Row(true, "and", false, false), new Row(false, "and", true, false), new Row(false, "and", false, false) };
LINQ分组实现
var groupedOperators = rows // 第一步:按操作符分组,生成每个操作符的真值表特征键 .GroupBy(row => row.OperatorName) .Select(opGroup => new { OperatorName = opGroup.Key, // 生成特征键:先按Left、Right排序(避免条目顺序不同导致误判),再拼接输入输出组合 TableSignature = string.Join("|", opGroup.OrderBy(r => r.Left).ThenBy(r => r.Right) .Select(r => $"{r.Left},{r.Right},{r.Result}")) }) // 第二步:按特征键分组,得到行为一致的操作符组 .GroupBy(item => item.TableSignature) .Select(signatureGroup => new { MatchingOperators = signatureGroup.Select(item => item.OperatorName).ToList(), // 可选:返回该组对应的真值表结构(取组内第一个操作符的条目) TruthTable = rows.Where(r => r.OperatorName == signatureGroup.First().OperatorName) .OrderBy(r => r.Left).ThenBy(r => r.Right) .Select(r => new { r.Left, r.Right, r.Result }) .ToList() });
输出结果遍历
foreach (var group in groupedOperators) { Console.WriteLine($"行为一致的操作符:{string.Join(", ", group.MatchingOperators)}"); Console.WriteLine("真值表:"); foreach (var row in group.TruthTable) { Console.WriteLine($"Left: {row.Left}, Right: {row.Right}, Result: {row.Result}"); } Console.WriteLine("---"); }
3. 关键细节说明
- 排序的必要性:必须对每个操作符的真值表条目按
Left和Right排序,避免因条目存储顺序不同导致特征键不一致。 - 特征键的可选方案:
- 字符串拼接:直观易读,适合小规模数据。
- 哈希值聚合:性能更优,适合大数据量场景,示例代码如下:
TableSignature = opGroup.OrderBy(r => r.Left).ThenBy(r => r.Right) .Select(r => HashCode.Combine(r.Left, r.Right, r.Result)) .Aggregate((currentHash, nextHash) => HashCode.Combine(currentHash, nextHash))
- 空值处理:
bool?类型的ToString()会输出True/False/空字符串,拼接时不会产生歧义。
内容的提问来源于stack exchange,提问作者user23207089
相关产品推荐
相关产品推荐

