使用值sortingstd :: map
我需要使用它的值而不是它的键来对std :: map进行sorting。 有没有一个简单的方法来做到这一点。
我在follwing线程中得到了一个解决scheme:
std :: map按数据sorting?
有没有更好的解决scheme。
map <long,double> testMap; //一些代码来生成地图中的值。 sort(testMap.begin(),testMap.end()); //有没有像这样的functionsorting地图?
即使正确的答案已经发布,我想我会添加一个演示如何可以做到这一点干净:
template<typename A, typename B> std::pair<B,A> flip_pair(const std::pair<A,B> &p) { return std::pair<B,A>(p.second, p.first); } template<typename A, typename B> std::multimap<B,A> flip_map(const std::map<A,B> &src) { std::multimap<B,A> dst; std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), flip_pair<A,B>); return dst; } int main(void) { std::map<int, double> src; ... std::multimap<double, int> dst = flip_map(src); // dst is now sorted by what used to be the value in src! }
通用关联源(需要C ++ 11)
如果对源联合容器(如std::unordered_map
)使用std::map
的替代方法,那么可以编写一个单独的重载,但最后该操作仍然是相同的,所以使用通用关联容器variadic模板可以用于任何映射结构:
// flips an associative container of A,B pairs to B,A pairs template<typename A, typename B, template<class,class,class...> class M, class... Args> std::multimap<B,A> flip_map(const M<A,B,Args...> &src) { std::multimap<B,A> dst; std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), flip_pair<A,B>); return dst; }
这对于std::map
和std::unordered_map
作为翻盖的来源都是有效的。
我需要类似的东西,但翻转的地图不适合我。 我只是把我的地图(下面的freq)复制到一个对的向量中,然后按照我想要的sorting对。
std::vector<std::pair<int, int>> pairs; for (auto itr = freq.begin(); itr != freq.end(); ++itr) pairs.push_back(*itr); sort(pairs.begin(), pairs.end(), [=](std::pair<int, int>& a, std::pair<int, int>& b) { return a.second < b.second; } );
如果要按sorting顺序显示地图中的值,请将地图中的值复制到vector中,然后对vector进行sorting。
我喜欢奥利(翻转地图)的答案,但似乎有一个问题:容器映射不允许具有相同键的两个元素。
一个解决scheme是使typesmultimap。 另一个是将src转储到一个向量中并对向量进行sorting。 前者需要对Oli的答案进行微小的修改,而后者则可以使用STL简明地复制来实现
#include <iostream> #include <utility> #include <map> #include <vector> #include <algorithm> using namespace std; int main() { map<int, int> m; m[11] = 1; m[22] = 2; m[33] = 3; vector<pair<int, int> > v; copy(m.begin(), m.end(), back_inserter<vector<pair<int, int> > >(v)); for (size_t i = 0; i < v.size(); ++i) { cout << v[i].first << " , " << v[i].second << "\n"; } return 0; };
你不能以这种方式对std::map
sorting,因为映射中的条目是按键sorting的。 如果你想按值sorting,你需要创build一个新的std::map
与交换的键和值。
map<long, double> testMap; map<double, long> testMap2; // Insert values from testMap to testMap2 // The values in testMap2 are sorted by the double value
请记住,双键在testMap2
必须是唯一的,或使用std::multimap
。
若要使用multimaps在Oli的解决scheme( https://stackoverflow.com/a/5056797/2472351 )上构build,可以将他使用的两个模板函数replace为以下内容:
template <typename A, typename B> multimap<B, A> flip_map(map<A,B> & src) { multimap<B,A> dst; for(map<A, B>::const_iterator it = src.begin(); it != src.end(); ++it) dst.insert(pair<B, A>(it -> second, it -> first)); return dst; }
下面是一个示例程序,显示了在执行翻转之后保留的所有键值对。
#include <iostream> #include <map> #include <string> #include <algorithm> using namespace std; template <typename A, typename B> multimap<B, A> flip_map(map<A,B> & src) { multimap<B,A> dst; for(map<A, B>::const_iterator it = src.begin(); it != src.end(); ++it) dst.insert(pair<B, A>(it -> second, it -> first)); return dst; } int main() { map<string, int> test; test["word"] = 1; test["spark"] = 15; test["the"] = 2; test["mail"] = 3; test["info"] = 3; test["sandwich"] = 15; cout << "Contents of original map:\n" << endl; for(map<string, int>::const_iterator it = test.begin(); it != test.end(); ++it) cout << it -> first << " " << it -> second << endl; multimap<int, string> reverseTest = flip_map(test); cout << "\nContents of flipped map in descending order:\n" << endl; for(multimap<int, string>::const_reverse_iterator it = reverseTest.rbegin(); it != reverseTest.rend(); ++it) cout << it -> first << " " << it -> second << endl; cout << endl; }
结果:
一个由它的值sorting的std::map
本质上是一个std::set
。 到目前为止,最简单的方法是将地图中的所有条目复制到一个集合(从这里采取和改编)
template <typename M, typename S> void MapToSet( const M & m, S & s ) { typename M::const_iterator end = m.end(); for( typename M::const_iterator it = m.begin(); it != end ; ++it ) { s.insert( it->second ); } }
一个警告:如果地图包含具有相同值的不同密钥,则它们将不会被插入到集合中并被丢失。
在下面的示例代码中,我写了一个简单的方法来输出word_map映射中的顶级单词,其中键是string(单词),值是无符号整数(单词出现)。
这个想法很简单,find当前的主要字,并从地图上删除它。 它没有被优化,但是在地图不大的时候效果很好,我们只需要输出前N个单词,而不是sorting整个地图。
const int NUMBER_OF_TOP_WORDS = 300; for (int i = 1; i <= NUMBER_OF_TOP_WORDS; i++) { if (word_map.empty()) break; // Go through the map and find the max item. int max_value = 0; string max_word = ""; for (const auto& kv : word_map) { if (kv.second > max_value) { max_value = kv.second; max_word = kv.first; } } // Erase this entry and print. word_map.erase(max_word); cout << "Top:" << i << " Count:" << max_value << " Word:<" << max_word << ">" << endl; }
翻转的结构可能不再是一个映射,而是一个多图,因此在上面的flip_map示例中,不是所有来自B的元素都必然出现在结果数据结构中。
你可以考虑使用boost :: bimap,它可能会让你感觉到map是按键和值同时sorting的(尽pipe这并不是真正发生的事情)