在Ceylon中使用Set
可以直接确定一个集合是否是另一个集合的超集。它只是first.superset(second)
。使用multiset(或包)语义对Iterable
,List
或Sequential
执行等效操作的最佳方法是什么?例如下面的伪代码:
{'a', 'b', 'b', 'c'}.containsAll({'b', 'a'}) // Should be true
{'a', 'b', 'b', 'c'}.containsAll({'a', 'a'}) // Should be false
答案 0 :(得分:4)
有Category.containsEvery
,由Iterable继承。它检查参数的每个元素是否包含在接收器中,因此bigger.containsEvery(smaller)
等同于:
smaller.every(bigger.contains)
(注意它是交换的。)这里括号中的表达式是方法引用,我们也可以用lambda编写这个扩展:
smaller.every(o => bigger.contains(o))
所以在你的例子中:
print({'a', 'b', 'b'}.containsEvery({'b', 'a'})); // Should be true
print({'a', 'b', 'b'}.containsEvery({'a', 'a'})); // Should be false
......实际上,这些都是真的。为什么你认为后者是假的?
您是否考虑过多重语义(即"超集&#34中的出现次数;迭代次数至少需要与较小的次数一样多)?或者你想要一个子列表?或者你只是想知道第二个迭代是否在第一个(startwith)的开头?
我不知道Ceylon的任何 multiset 实现(我发现了multimap)。如果你在JVM上运行,你可以使用任何Java,比如来自Guava(虽然它也没有"包含所有带有倍数"函数,据我所知)。
对于小型迭代,您可以使用.frequencies()
然后比较数字:
Boolean isSuperMultiset<Element>({Element*} bigger,
{Element*} smaller) =>
let (bigFreq = bigger.frequencies())
every({ for(key->count in smaller.frequencies())
count <= (bigFreq[key] else 0) })
对于子列表语义,SearchableList接口具有includes
方法,该方法检查另一个列表是否是子列表。 (它不是由很多类实现的,但是,你需要将你的第一个iterable转换为一个Array,假设它不是一个String / StringBuilder。)
对于startsWith语义,您可以将两者都转换为列表,然后使用List.startsWith
。应该有一种更有效的方法(你可以并行浏览两个迭代器)。
有corresponding
,但它只是在较短的一个结束后停止(即它回答问题&#34;这两个迭代中的任何一个是从另一个开始的#34;,而不知道哪一个是更长的一个)。对于ceylon.language中的一堆其他对相关函数也是如此。
如果你知道两个Iterables的长度(或者确信.size
很快),那应该可以解决问题:
Boolean startsWith<Element>({Element*}longer, {Element*}shorter) =>
shorter.size <= longer.size &&
corresponding(longer, shorter);
答案 1 :(得分:1)
如果您有两个Sequential
,那么您可以从左侧序列中逐个删除每个右手角色,直到您将其全部删除或无法删除其中一个。
Boolean containsAll<Element>([Element*] collection, [Element*] other)
given Element satisfies Object {
variable value remaining = collection;
for (element1 in other) {
value position = remaining.locate((element2) => element1 == element2);
if (exists position) {
remaining = remaining.initial(position.key).append(remaining.spanFrom(position.key + 1));
} else {
// Element was not found in remaining; terminate early
return false;
}
}
// All elements were found
return true;
}
print(containsAll(['a', 'b', 'b', 'c'], ['a', 'b']));
print(containsAll(['a', 'b', 'b', 'c'], ['a', 'a']));
附加仅存在于Sequential
上,因此它不仅适用于List
或Iterable
。
答案 2 :(得分:0)