c++ STL set difference

C++StlSetStdsetSet Difference

C++ Problem Overview


Does the C++ STL set data structure have a set difference operator?

C++ Solutions


Solution 1 - C++

Yes there is, it is in <algorithm> and is called: std::set_difference. The usage is:

#include <algorithm>
#include <set>
#include <iterator>
// ...
std::set<int> s1, s2;
// Fill in s1 and s2 with values
std::set<int> result;
std::set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(),
    std::inserter(result, result.end()));

In the end, the set result will contain the s1-s2.

Solution 2 - C++

Yes, there is a http://www.sgi.com/tech/stl/set_difference.html">set_difference</a> function in the algorithms header.

Edits:

FYI, the set data structure is able to efficiently use that algorithm, as stated in its http://www.sgi.com/tech/stl/set.html">documentation</a>;. The algorithm also works not just on sets but on any pair of iterators over sorted collections.

As others have mentioned, this is an external algorithm, not a method. Presumably that's fine for your application.

Solution 3 - C++

Not an "operator" in the language sense, but there is the set_difference algorithm in the standard library:

http://www.cplusplus.com/reference/algorithm/set_difference.html

Of course, the other basic set operations are present too - (union etc), as suggested by the "See also" section at the end of the linked article.

Solution 4 - C++

Once again, boost to the rescue:

#include <string>
#include <set>
#include <boost/range/algorithm/set_algorithm.hpp>

std::set<std::string> set0, set1, setDifference;
boost::set_difference(set0, set1, std::inserter(setDifference, setDifference.begin());

setDifference will contain set0-set1.

Solution 5 - C++

C++ does not define a set difference operator but you can define your own (using code given in other responses):

template<class T>
set<T> operator -(set<T> reference, set<T> items_to_remove)
{
    set<T> result;
    std::set_difference(
        reference.begin(), reference.end(),
        items_to_remove.begin(), items_to_remove.end(),
        std::inserter(result, result.end()));
    return result;
}

Solution 6 - C++

The chosen answer is correct, but has some syntax errors.

Instead of

#include <algorithms>

use

#include <algorithm>

Instead of

std::insert_iterator(result, result.end()));

use

std::insert_iterator<set<int> >(result, result.end()));

Solution 7 - C++

Not as a method but there's the external algorithm function set_difference

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1,
                              InputIterator2 first2, InputIterator2 last2,
                              OutputIterator result);

http://www.sgi.com/tech/stl/set_difference.html

Solution 8 - C++

Apparently, it does.

SGI - set_difference

Solution 9 - C++

All of the answers I see here are O(n). Wouldn't this be better?:

template <class Key, class Compare, class Allocator>   
std::set<Key, Compare, Allocator> 
set_subtract(std::set<Key, Compare, Allocator>&& lhs,
             const std::set<Key, Compare, Allocator>& rhs) {
    if (lhs.empty()) { return lhs; }
    // First narrow down the overlapping range:
    const auto rhsbeg = rhs.lower_bound(*lhs.begin());
    const auto rhsend = rhs.upper_bound(*lhs.rbegin());
    for (auto i = rhsbeg; i != rhsend; ++i) {
        lhs.erase(*i);
    }
    return std::move(lhs);
}

That seems to do the right thing. I'm not sure how to deal with the case that Compare's type doesn't fully specify its behavior, as in if Compare is a std::function<bool(int,int)>, but aside from that, this seems to work right and should be like O((num overlapping) • log(lhs.size())).

In the case that lhs doesn't contain *i, it's probably possible to optimize further by doing an O(log(rhs.size())) search for the next element of rhs that's >= the next element of lhs. That would optimize the case that lhs = {0, 1000} and rhs = {1, 2, ..., 999} to do the subtraction in log time.

Solution 10 - C++

can we just use

 set_difference(set1.begin(), set1.end(), set2.begin(). set2,end(),std::back_inserter(result)).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteveView Question on Stackoverflow
Solution 1 - C++PierreBdRView Answer on Stackoverflow
Solution 2 - C++Mr FoozView Answer on Stackoverflow
Solution 3 - C++philsquaredView Answer on Stackoverflow
Solution 4 - C++strickliView Answer on Stackoverflow
Solution 5 - C++astraujumsView Answer on Stackoverflow
Solution 6 - C++View Answer on Stackoverflow
Solution 7 - C++Ian GView Answer on Stackoverflow
Solution 8 - C++LeppyR64View Answer on Stackoverflow
Solution 9 - C++BenView Answer on Stackoverflow
Solution 10 - C++user1830108View Answer on Stackoverflow