std::set_intersection
允许我通过将元素输出到输出迭代器来检索两个std::set
实例之间的所有共同元素。在我的特殊情况下,我只对检查两个集合是否有任何共同元素感兴趣。
我目前的解决方案是使用boost::function_output_iterator
设置bool
变量,如下所示:
bool b{false};
set_intersection(begin(s0), end(s0),
begin(s1), end(s1),
make_function_output_iterator([&](const auto&){ b = true; }));
return b;
不幸的是,如果找到匹配项,此解决方案不会提前返回:必须完全遍历(即没有提前返回/短路)。
是否可以在早期返回时使用set_intersection
?我能想到的唯一解决方案是从function_output_iterator
函数对象中抛出异常,这是一个可怕的想法。
如果没有,标准库中还有其他可以帮助我的内容,还是我被迫重新实现set_intersection
?奖金问题:set_intersection
界面如果允许提前终止(即什么是标准库算法可能具有的#34;最通用"接口),将如何看待?
答案 0 :(得分:9)
好吧,被“强迫”重新实现std::set_intersection
并不是一件坏事。 &LT g取代;它只有大约五行代码:
template <class I1, class I2>
bool have_common_element(I1 first1, I1 last1, I2 first2, I2 last2) {
while (first1 != last1 && first2 != last2) {
if (*first1 < *first2)
++first1;
else if (*first2 < *first1)
++first2;
else
return true;
}
return false;
}
好的,超过5行。但无痛。
答案 1 :(得分:3)
这个简单的算法应该这样做:
#include <set>
#include <ciso646>
#include <iostream>
#include <cassert>
#include <functional>
template<class I1, class I2, class Comp = std::less<> >
bool has_element_in_common(I1 first1, I1 last1, I2 first2, I2 last2, Comp&& comp = Comp())
{
while (first1 != last1 and first2 != last2)
{
if (comp(*first1, *first2))
{
++first1;
}
else if (comp(*first2, *first1))
{
++first2;
}
else
{
return true;
}
}
return false;
}
int main()
{
auto s1 = std::set<int> { 1, 3, 5, 7, 9 };
auto s2 = std::set<int> { 2, 3, 4, 6, 8 };
assert(has_element_in_common(begin(s1), end(s1), begin(s2), end(s2)));
auto s3 = std::set<int> { 2, 4, 6, 8 };
assert(!has_element_in_common(begin(s1), end(s1),
begin(s3), end(s3)));
}
如果你想优化它以跳过多重集中的重复项,那么它需要做一些工作。
答案 2 :(得分:0)
你可以抛出异常,虽然异常开销很大......根据编程风格,你不应该像这样使用它:
bool find=false;
try{
set_intersection(begin(s0), end(s0),
begin(s1), end(s1),
make_function_output_iterator([&](const auto&){throw true;}));
}catch{
find= true;
}