sorting map using callback function in sort() - c++

I have a unordered_map<int,int> type variable. I want to sort the map according to its value. I was wondering if I can use callback in sort function, so that it returns sorted map according to it's value.
unordered_map<int,int> p;
for(int i=0;i<nums.size();i++){
p[nums[i]]++;
}
sort(p.begin(),p.end(),callback);

You can't sort a unordered_map in-place. You need to build a sortable alternate container, dump the content there (or bring appropriate material necessary to reference the pairs in the original map), then sort away. There are a multitude of ways to accomplish this. A few examples are shown below.
Value Copy and Sort
The following generates one-hundred random draws in the inclusive domain 1..10, then prints the frequency table after sorting based on frequency (value) descending (the unspoken task I suspect to be driving all of this to begin with):
#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <random>
int main()
{
std::mt19937 rng{ std::random_device{}() };
std::uniform_int_distribution<> dist(1, 10);
std::unordered_map<int, int> p;
for (int i = 0; i < 100; ++p[dist(rng)], ++i);
std::vector<std::pair<int,int>> v { p.begin(), p.end() };
std::sort(v.begin(), v.end(),
[](auto const& pr1, auto const& pr2)
{ return pr2.second < pr1.second; });
for (auto const& pr : v)
std::cout << pr.first << ':' << pr.second << '\n';
}
Output (varies)
3:14
4:13
7:13
9:11
1:11
2:10
10:7
6:7
8:7
5:7
Pointers to Pairs
An alternate mechanism using constant pointers to the original map pairs is also possible (and probably preferable if the mapped content is either too expensive or outright impossible to make copies of):
#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <random>
int main()
{
std::mt19937 rng{ std::random_device{}() };
std::uniform_int_distribution<> dist(1, 10);
std::unordered_map<int, int> p;
for (int i = 0; i < 100; ++p[dist(rng)], ++i);
std::vector<const decltype(p)::value_type*> v;
for (auto const& pr : p)
v.emplace_back(&pr);
std::sort(v.begin(), v.end(),
[](auto const& pr1, auto const& pr2)
{ return pr2->second < pr1->second; });
for (auto const& pr : v)
std::cout << pr->first << ':' << pr->second << '\n';
}
Output (varies)
2:16
1:14
3:11
7:11
4:9
10:9
5:8
8:8
9:8
6:6
Caveats apply to this approach. Those pointers to pairs are only as good as the day they were cashed. E.g., modify the original map by shoving new keys in, or trimming existing keys out, and the entire pointer bed is disavowed. That obviously includes outright destroying the original map. Buyer beware.

You are addressing 2 problems here:
Sorting a std::map or std::unordered_map according to its value
Using a kind of "compare callback" function for std::sort
Let us first tackle the point 2. If we read the description of std::sort in the CPP Reference here, then we see that can use a "comparison function object" as the 3rd parameter. This can be implemented with a Lambda, a functor or with adding a comparison operator to the object that will be sorted.
Let us assume we have a struct in a std::vector that we want to sort.
struct IntVal {
int val{};
};
std::vector<IntVal> intVals{};
If we want to sort this with a Lambda, then:
std::sort(intVals.begin(), intVals.end(), [](const IntVal& iv1, const IntVal& iv2) { return iv1.val < iv2.val; });
Or, you could add a comparison operator to your class/struct:
struct IntVal{
int val{};
bool operator < (const IntVal& other) const { return val < other.val; }
};
Or you can make your class a Functor, by adding a callable operator () to it.
#include <iostream>
#include <vector>
#include <algorithm>
struct IntVal{
int val{};
bool operator () (const IntVal& iv1, const IntVal& iv2) const { return iv1.val < iv2.val; }
};
std::vector<IntVal> intVals{ {3},{2},{1} };
int main() {
std::sort(intVals.begin(), intVals.end(), IntVal());
for (const IntVal& iv : intVals)
std::cout << iv.val << '\n';
}
Or, if you cannot modify the class, the create an external functor:
#include <iostream>
#include <vector>
#include <algorithm>
struct IntVal{
int val{};
};
// Functor
struct Comp {
bool operator () (const IntVal& iv1, const IntVal& iv2) const { return iv1.val < iv2.val; }
};
std::vector<IntVal> intVals{ {3},{2},{1} };
int main() {
std::sort(intVals.begin(), intVals.end(), Comp());
for (const IntVal& iv : intVals)
std::cout << iv.val << '\n';
}
Coming to the next topic.
You want to sort the data, stored in the std::unordered_map by its "value"-type.
This is not possible in place, because the nature of the maps is that they are already sorted. You cannot resort them. This would violate their internal behaviour.
The second problem is often that there key is unique. And sorting could also probaly destroy this strict requirement.
The solution is to use a second container. With you above mentioned "Sort" parameter. Copy the data to a second container and sort this.
We can use a std::vector and its range constructor to copy the data.
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <utility>
// Functor
struct Comp {
bool operator () (const std::pair<int,int>& p1, const std::pair<int, int>& p2) { return (p1.second == p2.second) ? p1.first<p2.first : p1.second>p2.second; }
};
int main() {
std::unordered_map<int, int> test{ {1,4},{2,3},{3,2},{4,1} };
std::vector<std::pair<int, int>> data(test.begin(), test.end());
std::sort(data.begin(), data.end(), Comp());
for (const auto[i1,i2] : data)
std::cout << i1 << ' ' << i2 << '\n';
}
Or, last but not least, and the final solution. We can use a 2nd container that will be sorted by definition, like a std::multiset
This will create a piece of code that is really easy to understand.
Please see:
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <utility>
#include <set>
// ------------------------------------------------------------
// Create aliases. Save typing work and make code more readable
using Pair = std::pair<int, int>;
// The map
using Map = std::unordered_map<Pair::first_type, Pair::second_type>;
// Sorted values will be stored in a multiset
struct Comp { bool operator ()(const Pair& p1, const Pair& p2) const { return (p1.second == p2.second) ? p1.first<p2.first : p1.second>p2.second; } };
using Sorter = std::multiset<Pair, Comp>;
int main() {
Map test{ {1,4},{2,3},{3,2},{4,1} };
Sorter sorter(test.begin(), test.end());
for (const auto[i1,i2] : sorter)
std::cout << i1 << ' ' << i2 << '\n';
}
And since what you really want to do is counting, please see an example for this as well. Here we will count as an example, the letters in a string:
#include <iostream>
#include <string>
#include <utility>
#include <set>
#include <unordered_map>
#include <type_traits>
#include <cctype>
// ------------------------------------------------------------
// Create aliases. Save typing work and make code more readable
using Pair = std::pair<char, unsigned int>;
// Standard approach for counter
using Counter = std::unordered_map<Pair::first_type, Pair::second_type>;
// Sorted values will be stored in a multiset
struct Comp { bool operator ()(const Pair& p1, const Pair& p2) const { return (p1.second == p2.second) ? p1.first<p2.first : p1.second>p2.second; } };
using Rank = std::multiset<Pair, Comp>;
// ------------------------------------------------------------
// --------------------------------------------------------------------------------------
// Compact function to calculate the frequency of charcters and then get their rank
Rank getRank(std::string& text) {
// Definition of our counter
Counter counter{};
// Iterate over all charcters in text and count their frequency
for (const char c : text) if (std::isalpha(c)) counter[char(std::tolower(c))]++;
// Return ranks,sorted by frequency and then sorted by character
return { counter.begin(), counter.end() };
}
// --------------------------------------------------------------------------------------
// Test, driver code
int main() {
// Get a string from the user
if (std::string text{}; std::getline(std::cin, text))
// Calculate rank and show result
for (const auto& [letter, count] : getRank(text))
std::cout << letter << " = " << count << '\n';
}

Related

How to sort map using comparator with reflection in original map?

How to sort the multimap using comparator.
It should be reflected in the multimap container
#include <bits/stdc++.h>
using namespace std;
// Comparator function to sort pairs
// according to second value
bool cmp(pair<string, int>& a,
pair<string, int>& b)
{
return a.second < b.second;
}
// Function to sort the map according
// to value in a (key-value) pairs
void sort(multimap<string, int>& M)
{
// Declare vector of pairs
vector<pair<string, int> > A;
// Copy key-value pair from Map
// to vector of pairs
for (auto& it : M) {
A.push_back(it);
}
// Sort using comparator function
sort(A.begin(), A.end(), cmp);
// Print the sorted value
for (auto& it : A) {
cout << it.first << ' '
<< it.second << endl;
}
}
// Driver Code
int main()
{
// Declare Map
multimap<string, int> M;
// Given Map
M = { { "GfG", 3 },
{ "To", 2 },
{ "Welcome", 1 } };
// Function Call
sort(M);
cout<<"\n";
for(auto i:M)
{
cout<<i.first<<" "<<i.second<<endl;
}
return 0;
}
This is code I got from Geekforgeeks!
I totally understood the concept but I need to know how to sort the map itself if the map is multimap.?
OUTPUT
Welcome 1
To 2
GfG 3
GfG 3
To 2
Welcome 1
Basically the answer has been given in the comments already. I will summarize again and show an alternative.
The background is that we often want to use the properties of an associative container, but later sort it by its value and not by the key.
The unsorted associative containers, like std::unsorted_set, std::unordered_map , std::unordered_multiset and std::unordered_multimap cannot be ordered, as their names say. They are using a hash algorithm to store and retrieve their values.
Please read also in the CPP Reference about STL container.
And, if we look at the sorted associative container, we see that the std::set and the std::multiset do not work with key value pairs and the other two, the std::map and std::multimap have a key and value but are always sorted by their key.
But as said, we often want to have the advantages of an Associative container with a key - value pair and later some sorted-by-the-value data.
This can only be acieved by using 2 container having the needed property. In your above example the data is copied into a std::vector and then sorted. This mechanism can be used always, with any sortable container, by adding a std::pair of key and value to a container. So:
using Pair = std::pair<std::string, int>;
using Conatiner = std::vector<Pair>;
An often needed use case is counting something. For example, counting the letters in a string. This can be really easily achieved with a std::map or std::unordered_map and the sorted by the value using a 2nd container. Please see some example code below:
#include <iostream>
#include <string>
#include <utility>
#include <set>
#include <unordered_map>
#include <type_traits>
// ------------------------------------------------------------
// Create aliases. Save typing work and make code more readable
using Pair = std::pair<char, unsigned int>;
// Standard approach for counter
using Counter = std::unordered_map<Pair::first_type, Pair::second_type>;
// Sorted values will be stored in a multiset, because their may be double ranks
struct Comp { bool operator ()(const Pair& p1, const Pair& p2) const { return (p1.second == p2.second) ? p1.first<p2.first : p1.second>p2.second; } };
using Rank = std::multiset<Pair, Comp>;
// ------------------------------------------------------------
// Function to get the rank of letters in a string
Rank getRank(const std::string& str) {
Counter counter;
for (const char c : str) counter[c]++;
return { counter.begin(), counter.end() };
}
// Test / Driver Code
int main() {
if (std::string userString{}; std::getline(std::cin, userString))
for (const auto& [letter, count] : getRank(userString))
std::cout << (int)letter << ' ' << count << ' ';
}
So, we use the property of the std::unordred map as a fast associative container, not sorted by the key, in combination with a std::multiset which will act as a "sorter".
Or, you can take a std::multiset from the beginning. Example:
#include <iostream>
#include <string>
#include <utility>
#include <set>
// ------------------------------------------------------------
// Create aliases. Save typing work and make code more readable
using Pair = std::pair <std::string, int> ;
// Sorted values will be stored in a multiset
struct Comp { bool operator ()(const Pair& p1, const Pair& p2) const { return (p1.second == p2.second) ? p1.first<p2.first : p1.second<p2.second; } };
using Sorted = std::multiset<Pair, Comp>;
// ------------------------------------------------------------
// Driver Code
int main()
{
Sorted data { { "GfG", 3 }, { "To", 2 }, { "Welcome", 1 } };
for (const auto& [key, value] : data)
std::cout << key << '\t' << value << '\n';
}
Depends of course all on what you want to achieve . . .

How to find Max value of second element of std::pair in std::vector?

I have vector of pairs in this order {{label, probability},{label, probability}}. I want to get the pair which has the maximum value of probability. Here's my attempt to accomplish that, but instead of getting the max value of probability, it returns the max value of the label string. e.g. label dog is the largest value because of alphabet order.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
std::vector<std::pair<std::string, float>> pairs;
pairs = {{"apple",34.785}, {"banana",67.8467}, {"dog", 13.476}, {"cat",56.486}};
const auto p = max_element(pairs.begin(), pairs.end());
auto label = p->first;
auto prob = p->second;
std::cout<<label<<" "<<prob;
}
Output : dog 13.476
You need to provide a customized comparator to max_element, e.g.
max_element(pairs.begin(),
pairs.end(),
[](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; });
Otherwise, std::max_element will use the operator< of std::pair as the comparator, which will check both the two elements of std::pair.
Note : works on C++14 and higher
LIVE
You can do this by custom comparator function.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
bool compare(std::pair<std::string, float> p1, std::pair<std::string, float> p2) {
return p1.second<p2.second;
}
int main()
{
std::vector<std::pair<std::string, float>> pairs;
pairs = {{"apple",34.785}, {"banana",67.8467}, {"dog", 13.476}, {"cat",56.486}};
const auto p = max_element(pairs.begin(), pairs.end(), compare);
auto label = p->first;
auto prob = p->second;
std::cout<<label<<" "<<prob;
}

C++ storing a value in an unordered pair

I want to store a floating point value for an unordered pair of an integers. I am unable to find any kind of easy to understand tutorials for this. E.g for the unordered pair {i,j} I want to store a floating point value f. How do I insert, store and retrieve values like this?
Simple way to handle unordered int pairs is using std::minmax(i,j) to generate std::pair<int,int>. This way you can implement your storage like this:
std::map<std::pair<int,int>,float> storage;
storage[std::minmax(i,j)] = 0.f;
storage[std::minmax(j,i)] = 1.f; //rewrites storage[(i,j)]
Admittedly proper hashing would give you some extra performance, but there is little harm in postponing this kind of optimization.
Here's some indicative code:
#include <iostream>
#include <unordered_map>
#include <utility>
struct Hasher
{
int operator()(const std::pair<int, int>& p) const
{
return p.first ^ (p.second << 7) ^ (p.second >> 3);
}
};
int main()
{
std::unordered_map<std::pair<int,int>, float, Hasher> m =
{ { {1,3}, 2.3 },
{ {2,3}, 4.234 },
{ {3,5}, -2 },
};
// do a lookup
std::cout << m[std::make_pair(2,3)] << '\n';
// add more data
m[std::make_pair(65,73)] = 1.23;
// output everything (unordered)
for (auto& x : m)
std::cout << x.first.first << ',' << x.first.second
<< ' ' << x.second << '\n';
}
Note that it relies on the convention that you store the unordered pairs with the lower number first (if they're not equal). You might find it convenient to write a support function that takes a pair and returns it in that order, so you can use that function when inserting new values in the map and when using a pair as a key for trying to find a value in the map.
Output:
4.234
3,5 -2
1,3 2.3
65,73 1.23
2,3 4.234
See it on ideone.com. If you want to make a better hash function, just hunt down an implementation of hash_combine (or use boost's) - plenty of questions here on SO explaining how to do that for std::pair<>s.
You implement a type UPair with your requirements and overload ::std::hash (which is the rare occasion that you are allowed to implement something in std).
#include <utility>
#include <unordered_map>
template <typename T>
class UPair {
private:
::std::pair<T,T> p;
public:
UPair(T a, T b) : p(::std::min(a,b),::std::max(a,b)) {
}
UPair(::std::pair<T,T> pair) : p(::std::min(pair.first,pair.second),::std::max(pair.first,pair.second)) {
}
friend bool operator==(UPair const& a, UPair const& b) {
return a.p == b.p;
}
operator ::std::pair<T,T>() const {
return p;
}
};
namespace std {
template <typename T>
struct hash<UPair<T>> {
::std::size_t operator()(UPair<T> const& up) const {
return ::std::hash<::std::size_t>()(
::std::hash<T>()(::std::pair<T,T>(up).first)
) ^
::std::hash<T>()(::std::pair<T,T>(up).second);
// the double hash is there to avoid the likely scenario of having the same value in .first and .second, resulinting in always 0
// that would be a problem for the unordered_map's performance
}
};
}
int main() {
::std::unordered_map<UPair<int>,float> um;
um[UPair<int>(3,7)] = 3.14;
um[UPair<int>(8,7)] = 2.71;
return 10*um[::std::make_pair(7,3)]; // correctly returns 31
}

boost::any_range and operator []

Consider the following code:
#include <boost/range.hpp>
#include <boost/range/any_range.hpp>
#include <boost/range/join.hpp>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <list>
struct TestData {
TestData() : m_strMem01("test"), m_intMem02(42), m_boolMem03(true) {}
std::string m_strMem01;
int m_intMem02;
bool m_boolMem03;
};
struct IntComp {
bool operator()(const TestData &s, int i) { return s.m_intMem02 < i; }
bool operator()(int i, const TestData &s) { return i < s.m_intMem02; }
bool operator()(const TestData &i, const TestData &s) {
return i.m_intMem02 < s.m_intMem02;
}
};
struct StrComp {
bool operator()(const TestData &s, const std::string &str) {
return s.m_strMem01 < str;
}
bool operator()(const std::string &str, const TestData &s) {
return str < s.m_strMem01;
}
bool operator()(const TestData &i, const TestData &s) {
return i.m_strMem01 < s.m_strMem01;
}
};
typedef boost::any_range<TestData, boost::forward_traversal_tag,
const TestData &, std::ptrdiff_t> TestRange;
std::vector<TestData> vecData(10);
std::list<TestData> listData(20);
TestRange foo() {
TestRange retVal;
auto tmp1 = std::equal_range(vecData.cbegin(), vecData.cend(), 42, IntComp());
retVal = boost::join(retVal, tmp1);
auto tmp2 =
std::equal_range(listData.cbegin(), listData.cend(), "test", StrComp());
retVal = boost::join(retVal, tmp2);
return retVal;
}
int main(int argc, char *argv[]) {
auto res = foo();
for (auto a : res) {
std::cout << a.m_strMem01 << std::endl;
}
//std::cout << res[4].m_intMem02 << std::endl;
}
If you uncomment the last line the code fails since distance_to not implemented for any_forward_iterator_interface. I'm not sure what exactly I'm missing here, like implementing operator[] or distance_to but for what? My own version traversal tag? And why it doesn't work in the first place?
Coliru version
I would say the answer depends on your performance needs and your laziness when it comes to implementing a new iterator abstraction. The core reason for your [] operator not working is the fact that std::list<...> does not provide a random access traversal iterator. If you would have chosen a container that provides such an iterator. You any_range<...> could have taken the random_access_traversal_tag and everything would be fine.
I think it's fair to say that it is not such a big deal to implement a random access iterator on top of a list by simply encapsulating the current index and count forward and backward within the list whenever a specific position is meant to be accessed, but it's clearly against the nature of the list performance-wise.
Is there a good reason to hold one of the collection in a list ?
Is there a good reason to access the resulting any_range by random ?
Is it worth the effort to provide a inefficient random access interface for std::list ?
Of course any_iterator (which underlies the any_range implementation) doesn't gratuitously emulate RandomAccess iterators for any odd iterator you pass.
If you want that, just make an iterator adaptor that does this (making it very slow to random access elements in a list - so don't do this).

How can I order a map by value efficiently?

Consider a std::map<K,V>. I want to re-order the map by value profiting by an appropriate container std::C<V*> or std::C<V&>, in a way that no copies of values are done to store the elements in C. Furthermore, elements in C must be sorted according to the result of int f(V&) applied to each element. Despite my efforts I could not find an appropriate C and an enough efficient way to build it. Do you have any solution? A small example would be much appreciated.
Seems simple enough.
std::map<K,V> src;
int f(V&) {return 0;}
V* get_second(std::pair<const K,V> &r) {return &(r.second);} //transformation
bool pred(V* l, V* r) { return f(*l)<f(*r); } //sorting predicate
std::vector<V*> dest(src.size()); //make destination big enough
std::transform(src.begin(), src.end(), dest.begin(), get_second); //transformcopy
std::sort(dest.begin(), dest.end(), pred); //sort
Unless you meant C is supposed to be another map:
std::pair<K,V*> shallow_pair(std::pair<const K,V> &r)
{return std::pair<K,V*>(r.first, &(r.second));}
std::map<K, V*> dest2;
std::transform(src.begin(), src.end(),
std::inserter(dest2,dest2.end()), shallow_pair);
http://ideone.com/bBoXq
This requires the previous map to remain in scope longer than dest, and have no pairs removed until dest is destructed. Otherwise src will need to have been holding smart pointers of some sort.
You can use std::reference_wrapper, like this:
#include <map>
#include <string>
#include <algorithm>
#include <functional>
#include <prettyprint.hpp>
#include <iostream>
template <typename T>
std::ostream & operator<<(std::ostream & o, std::reference_wrapper<T> const & rw)
{
return o << rw.get();
}
int main()
{
std::map<int, std::string> m { { 1, "hello"}, { 2, "aardvark" } };
std::cout << m << std::endl;
std::vector<std::reference_wrapper<std::string>> v;
for (auto & p : m) v.emplace_back(p.second);
std::cout << v << std::endl;
std::sort(v.begin(), v.end(), std::less<std::string>); // or your own predicate
std::cout << v << std::endl;
v.front().get() = "world";
std::cout << m << std::endl;
}
This prints:
[(1, hello), (2, aardvark)]
[hello, aardvark]
[aardvark, hello]
[(1, hello), (2, world)]
Sounds like you are using multiple containers to represent multiple views into the same dataset. The trouble with this approach is in keeping the containers synchronized and avoiding dangling pointer issues. Boost.MultiIndex was made for just this purpose. A boost::multi_index container stores only one copy of each element, but allows you to access the elements via several indices.
Example:
#include <iterator>
#include <iostream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <boost/multi_index/member.hpp>
typedef std::string Key;
typedef int Value;
struct Record
{
Record(const Key& key, Value value) : key(key), value(value) {}
Key key;
Value value;
};
inline std::ostream& operator<<(std::ostream& os, const Record& rec)
{
os << rec.key << " " << rec.value << "\n";
return os;
}
inline int sortFunc(const Record& rec) {return -rec.value;}
struct ByNumber{}; // tag
namespace bmi = boost::multi_index;
typedef bmi::multi_index_container<
Record,
bmi::indexed_by<
// sort by key like a std::map
bmi::ordered_unique< bmi::member<Record, Key, &Record::key> >,
// sort by less<int> on free function sortFunc(const Record&)
bmi::ordered_non_unique<bmi::tag<ByNumber>,
bmi::global_fun<const Record&, int, &sortFunc> >
>
> RecordSet;
typedef RecordSet::index<ByNumber>::type RecordsByNumber;
int main()
{
RecordSet rs;
rs.insert(Record("alpha", -1));
rs.insert(Record("charlie", -2));
rs.insert(Record("bravo", -3));
RecordsByNumber& byNum = rs.get<ByNumber>();
std::ostream_iterator<Record> osit(std::cout);
std::cout << "Records sorted by key:\n";
std::copy(rs.begin(), rs.end(), osit);
std::cout << "\nRecords sorted by sortFunc(const Record&):\n";
std::copy(byNum.begin(), byNum.end(), osit);
}
Result:
Records sorted by key:
alpha -1
bravo -3
charlie -2
Records sorted by sortFunc(const Record&):
alpha -1
charlie -2
bravo -3
The place I'd start is to:
look at Boost::bimap
create ordering from V -> K via a comparator function object which evaluates f(V&) the way you suggested. (e.g. as in std::map<K,V,C> where C is a comparator class)
How about,
std::set<boost::shared_ptr<V>, compfunc>
where compfunc is a functor which takes two shared_ptr objects and applies the logic in your function?
Excuse the formatting, not good on my phone.
How about something like this (untested pseudo code):
V* g(pair<K,V> &v) { return &v.second; }
bool cmp(V* a, V* b) { return f(*a) < f(*b); }
map<K,V> map;
vector<V*> vec;
vec.reserve(map.size());
transform(map.begin(), map.end(), back_inserter(vec), g);
sort(vec.begin(), vec.end(), cmp);