First option: cluster() and sort_within()
A handwritten double loop by @MadScienceDreams can be written as a cluster() algorithm of complexity O(N * K) with elements N and clusters K He repeatedly calls std::partition (using the C ++ 14 style with common lambdas, easily adapting to C ++ 1 or even C ++ 98 style by writing your own function objects):
template<class FwdIt, class Equal = std::equal_to<>> void cluster(FwdIt first, FwdIt last, Equal eq = Equal{}) { for (auto it = first; it != last; ) it = std::partition(it, last, [=](auto const& elem){ return eq(elem, *it); }); }
which you call on your input vector<std::pair> as
cluster(begin(v), end(v), [](auto const& L, auto const& R){ return L.first == R.first; });
The next algorithm for writing is sort_within , which takes two predicates: an equality and an object of the comparison function, and calls std::find_if_not to find the end of the current range, and then std::sort to sort within that range
template<class RndIt, class Equal = std::equal_to<>, class Compare = std::less<>> void sort_within(RndIt first, RndIt last, Equal eq = Equal{}, Compare cmp = Compare{}) { for (auto it = first; it != last; ) { auto next = std::find_if_not(it, last, [=](auto const& elem){ return eq(elem, *it); }); std::sort(it, next, cmp); it = next; } }
On an already grouped input, you can name it as:
sort_within(begin(v), end(v), [](auto const& L, auto const& R){ return L.first == R.first; }, [](auto const& L, auto const& R){ return L.second < R.second; } );
A live example that shows it for some real data with std::pair<int, int> .
Second option: custom comparison
Even if there is no operator< in A , you can define it yourself. There are two broad options here. First, if A hashable, you can define
bool operator<(A const& L, A const& R) { return std::hash<A>()(L) < std::hash<A>()(R); }
and write std::sort(begin(v), end(v)) directly. You will have an O(N log N) call to std::hash if you do not want to cache all unique hash values ββin a separate storage.
Secondly, if A not hashed, but has data members x() , y() and z() that uniquely determine equality on A : you can do
bool operator<(A const& L, A const& R) { return std::tie(Lx(), Ly(), Lz()) < std::tie(Rx(), Ry(), Rz()); }
Again, you can directly write std::sort(begin(v), end(v)) .