如何判断一个列表是否包含另一个列表的全部元素(含重复校验)
如何判断一个列表包含另一个列表的全部元素(含重复元素校验)
需求场景
需要判断集合A是否包含集合B的所有元素,且A中每个元素的出现次数不小于B中的对应次数:
- 示例1:
(a,b,c,d)包含(c,a,d)→ 返回true - 示例2:
(a,b,c,d)包含(b,b,c,d)→ 返回false(A中仅1个b,B中需要2个)
原方案问题
你之前使用HashSet<T>.IsSupersetOf的方法无法处理重复元素场景,因为HashSet会自动去重,导致示例2错误返回true。
解决方案
核心思路是统计元素的出现频次,再逐一比对目标集合中每个元素的频次是否不超过源集合的频次,以下两种实现方式都可以满足需求:
方式1:用Dictionary手动统计频次
static bool ContainsAllElementsWithFrequency<T>(IEnumerable<T> source, IEnumerable<T> target) { var sourceCount = new Dictionary<T, int>(); // 统计源集合中每个元素的出现次数 foreach (var item in source) { if (sourceCount.TryGetValue(item, out int count)) sourceCount[item] = count + 1; else sourceCount[item] = 1; } // 校验目标集合的每个元素频次是否足够 foreach (var item in target) { if (!sourceCount.TryGetValue(item, out int count) || count == 0) return false; sourceCount[item] = count - 1; } return true; }
方式2:用LINQ GroupBy简化统计
static bool ContainsAllElementsWithFrequency<T>(IEnumerable<T> source, IEnumerable<T> target) { // 分组统计源集合和目标集合的元素频次 var sourceFreq = source.GroupBy(x => x).ToDictionary(g => g.Key, g => g.Count()); var targetFreq = target.GroupBy(x => x); // 逐一比对每个元素的频次 foreach (var group in targetFreq) { if (!sourceFreq.TryGetValue(group.Key, out int sourceCount) || sourceCount < group.Count()) return false; } return true; }
逻辑说明
- 先统计源集合中每个元素的出现次数
- 遍历目标集合的元素(或分组),检查源集合中对应元素的剩余次数是否足够
- 只要有一个元素不满足频次要求,立即返回
false;全部校验通过则返回true
示例验证
- 对示例1:目标集合的元素a、c、d各出现1次,源集合中均有足够次数,返回
true - 对示例2:目标集合中b出现2次,源集合仅1次,返回
false,符合预期
内容的提问来源于stack exchange,提问作者user20424619
相关产品推荐
相关产品推荐

