diff --git a/libwccl/ops/functions/setops.h b/libwccl/ops/functions/setops.h index bdf20594d075ee2898a3c9bef037ed87a0a67b93..d53cedc3ea222b7a282ff21cf8fabb793d8b9b81 100644 --- a/libwccl/ops/functions/setops.h +++ b/libwccl/ops/functions/setops.h @@ -6,6 +6,7 @@ #include <libwccl/values/strset.h> namespace Wccl { + typedef boost::shared_ptr<StrSet> StrSetPtr; template<class T> class SetListOperator : public ListOperator<T> @@ -84,12 +85,9 @@ FunctionBase::BaseRetValPtr SetUnion<StrSet>::apply_internal(const FunExecContex boost::shared_ptr<StrSet> out = boost::make_shared<StrSet>(); if (expressions_->empty()) return out; const boost::shared_ptr<const StrSet>& set1 = (*expressions_)[0]->apply(context); - const boost::shared_ptr<const StrSet>& set2 = (*expressions_)[1]->apply(context); - std::set_union(set1->contents().begin(), set1->contents().end(), - set2->contents().begin(), set2->contents().end(), - std::inserter(out->contents(), out->contents().begin())); + out->contents() = set1->contents(); - for (size_t i = 2; i < expressions_->size(); ++i) { + for (size_t i = 1; i < expressions_->size(); ++i) { const boost::shared_ptr<const StrSet>& seti = (*expressions_)[i]->apply(context); foreach (const UnicodeString& s, seti->contents()) { out->insert(s); @@ -116,20 +114,40 @@ FunctionBase::BaseRetValPtr SetIntersection<StrSet>::apply_internal(const FunExe if (expressions_->size() == 1) return expressions_->front()->apply(context); boost::shared_ptr<StrSet> out = boost::make_shared<StrSet>(); if (expressions_->empty()) return out; - const boost::shared_ptr<const StrSet>& set1 = (*expressions_)[0]->apply(context); - const boost::shared_ptr<const StrSet>& set2 = (*expressions_)[1]->apply(context); - std::set_intersection(set1->contents().begin(), set1->contents().end(), - set2->contents().begin(), set2->contents().end(), - std::inserter(out->contents(), out->contents().begin())); - for (size_t i = 2; i < expressions_->size(); ++i) { - boost::shared_ptr<StrSet> out2 = boost::make_shared<StrSet>(); - const boost::shared_ptr<const StrSet>& seti = (*expressions_)[i]->apply(context); - std::set_intersection(seti->contents().begin(), seti->contents().end(), - out->contents().begin(), out->contents().end(), - std::inserter(out->contents(), out2->contents().begin())); - out->contents().swap(out2->contents()); + + //find smallest set + size_t smallest = 0; + size_t smallest_size = (std::numeric_limits<size_t>::max)(); + for (size_t i = 0; i < expressions_->size(); ++i) { + const boost::shared_ptr<const StrSet>& set1 = (*expressions_)[i]->apply(context); + size_t ssize = set1->size(); + if(ssize < smallest_size){ + smallest = i; + smallest_size = ssize; + } + } + + const boost::shared_ptr<const StrSet>& smallest_set = (*expressions_)[smallest]->apply(context); + //for each element in smallest set + foreach (const UnicodeString& s, smallest_set->contents()) { + bool everywhere = true; + // find if every other set contains this element + for (size_t i = 0; i < expressions_->size() && everywhere; ++i) { + if (i == smallest) + continue; + const boost::shared_ptr<const StrSet>& set1 = (*expressions_)[i]->apply(context); + + if(set1->contents().find(s) == set1->contents().end()) + everywhere = false; + } + if(everywhere) + out->insert(s); } + + + + return out; } diff --git a/tests/data/setops.ccl b/tests/data/setops.ccl new file mode 100644 index 0000000000000000000000000000000000000000..a295b1b83785b031dd95f72f9d6cfe93c782c9d3 --- /dev/null +++ b/tests/data/setops.ccl @@ -0,0 +1,10 @@ +--- +intersection(["ala","ma","kota"], ["kota", "kij"]) + +["kota"] +--- + +inter(union(["ala","ma","kota"], ["kota", "kij"]), ["ala", "ma", "kota", "kij"]) + +True +---