如何在Ceylon中对Iterable、List等集合实现多重集语义的全元素包含检测?
在Ceylon中用多重集语义判断Iterable/List/Sequential的超集
嘿,这个问题问到点子上了!Ceylon里Set的超集判断确实一句first.superset(second)就搞定,但要给Iterable、List这类允许重复元素的集合做多重集(bag)语义的超集检查,就得考虑每个元素的出现次数了——毕竟像{'a','b','b','c'}这种集合,能包含{'b','a'}但肯定包含不了{'a','a'}对吧?
咱们的核心思路是:先把两个集合转换成「元素-出现次数」的频率映射,再逐一比对第二个集合里每个元素的出现次数是否都不超过第一个集合的对应次数。
第一步:写个工具函数统计元素频率
先实现一个通用函数,把任意Iterable转换成记录元素出现次数的HashMap:
HashMap<Element, Integer> getElementFrequency<Element>(Iterable<Element> iterable) { value frequencyMap = HashMap<Element, Integer>(); for (element in iterable) { // 若元素已存在则次数+1,不存在则初始化为1 frequencyMap[element] = (frequencyMap[element] else 0) + 1; } return frequencyMap; }
第二步:实现多重集语义的containsAll
基于上面的频率映射,咱们就能写出符合需求的判断函数了:
Boolean containsAllBag<Element>(Iterable<Element> source, Iterable<Element> target) { // 先做快速校验:如果目标集合元素总数比源集合多,直接返回false value sourceSize = source.size; value targetSize = target.size; if (targetSize > sourceSize) { return false; } value sourceFreq = getElementFrequency(source); value targetFreq = getElementFrequency(target); // 遍历目标集合的频率映射,逐一比对次数 for ((element, requiredCount) in targetFreq) { value availableCount = sourceFreq[element] else 0; if (availableCount < requiredCount) { return false; } } return true; }
测试你的示例
用你给的例子测试一下,完全符合预期:
value sampleList = {'a', 'b', 'b', 'c'}; print(containsAllBag(sampleList, {'b', 'a'})); // 输出true print(containsAllBag(sampleList, {'a', 'a'})); // 输出false
而且这个函数对List、Sequential类型也完全适用,因为它们都实现了Iterable接口,不用做任何额外修改就能直接用~
内容的提问来源于stack exchange,提问作者drhagen
相关产品推荐
相关产品推荐

