値でソートするSTLマップを実装するにはどうすればよいですか?
たとえば、マップm
があります。
map<int, int> m;
m[1] = 10;
m[2] = 5;
m[4] = 6;
m[6] = 1;
そのマップをm
の値でソートしたいと思います。したがって、マップを印刷する場合、次のように結果を取得します。
m[6] = 1
m[2] = 5
m[4] = 6
m[1] = 10
この方法でマップを並べ替えるにはどうすればよいですか?キーと値をソートされた値で処理できる方法はありますか?
最初のマップの値をキーとして、最初のマップのキーを値として、2番目のマップを作成できます。
これは、すべての値が異なる場合にのみ機能します。これを想定できない場合は、マップの代わりにマルチマップを構築する必要があります。
すべてのキーと値のペアを最初にset<pair<K, V> >
にダンプします。ここで、set
は、ペアの2番目の値のみを比較するより小さいファンクターで構築されます。そうすれば、値がすべて異なっていなくてもコードは機能します。
または、キーと値のペアをvector<pair<K, V> >
にダンプし、その後、そのベクトルを同じより小さいファンクターでソートします。
値でソートするSTLマップをどのように実装できますか。
できません、定義による。マップは、キーで要素を並べ替えるデータ構造です。
このようなことには Boost.Bimap を使用する必要があります。
@swegiのアイデアに基づいて、multimap
を使用して c ++ 11 でソリューションを実装しました。
_map<int, int> m = {{1, 10}, {2, 5}, {4, 6}, {6, 1}};
multimap<int, int> mm;
for(auto const &kv : m)
mm.insert(make_pair(kv.second, kv.first)); // Flip the pairs.
for(auto const &kv : mm)
cout << "m[" << kv.second << "] = " << kv.first << endl; // Flip the pairs again.
_
また、ペアのベクトルを使用して、@ Chrisのアイデアに基づいたC++ 11ソリューションを実装しました。正しいソートのために、比較ファンクターとして lambda expression を提供しています:
_map<int, int> m = {{1, 10}, {2, 5}, {4, 6}, {6, 1}};
using mypair = pair<int, int>;
vector<mypair> v(begin(m), end(m));
sort(begin(v), end(v), [](const mypair& a, const mypair& b) { return a.second < b.second; });
for(auto const &p : v)
cout << "m[" << p.first << "] = " << p.second << endl;
_
最初のソリューションはよりコンパクトですが、両方のソリューションのパフォーマンスはほぼ同じです。 multimap
への挿入はO(log n)ですが、これはnエントリに対して行う必要があります、O(n log n)になります。 2番目のソリューションでベクトルを並べ替えると、O(n log n)になります。
また、ペアのセットの使用に関する@Chrisのアイデアも試してみました。ただし、値がすべて異なる場合は機能しません。ペアの2番目の要素のみを比較するファンクターを使用しても役に立ちません。最初にmake_pair(1, 1)
をセットに挿入してからmake_pair(2, 1)
を挿入しようとすると、2番目のペアは挿入されません。両方のペアはそのセットで同一と見なされるためです。その効果を見ることができます ここでIdeone 。
私はちょうど私のc ++本で同様の質問をしました。しかし、私が思いついた答えはあまり効率的ではないかもしれません:
int main()
{
string s;
map<string, int> counters;
while(cin >> s)
++counters[s];
//Get the largest and smallest values from map
int beginPos = smallest_map_value(counters);
int endPos = largest_map_value(counters);
//Increment through smallest value to largest values found
for(int i = beginPos; i <= endPos; ++i)
{
//For each increment, go through the map...
for(map<string, int>::const_iterator it = counters.begin(); it != counters.end(); ++it)
{
//...and print out any pairs with matching values
if(it->second == i)
{
cout << it->first << "\t" << it->second << endl;
}
}
}
return 0;
}
//Find the smallest value for a map<string, int>
int smallest_map_value(const map<string, int>& m)
{
map<string, int>::const_iterator it = m.begin();
int lowest = it->second;
for(map<string, int>::const_iterator it = m.begin(); it != m.end(); ++it)
{
if(it->second < lowest)
lowest = it->second;
}
return lowest;
}
//Find the largest value for a map<string, int>
int largest_map_value(const map<string, int>& m)
{
map<string, int>::const_iterator it = m.begin();
int highest = it->second;
for(map<string, int>::const_iterator it = m.begin(); it != m.end(); ++it)
{
if(it->second > highest)
highest = it->second;
}
return highest;
}
私はこれを thispointer で見つけました。この例では、すべてのint値でstd :: map <std :: string、int>をソートします。
#include <map>
#include <set>
#include <algorithm>
#include <functional>
int main() {
// Creating & Initializing a map of String & Ints
std::map<std::string, int> mapOfWordCount = { { "aaa", 10 }, { "ddd", 41 },
{ "bbb", 62 }, { "ccc", 13 } };
// Declaring the type of Predicate that accepts 2 pairs and return a bool
typedef std::function<bool(std::pair<std::string, int>, std::pair<std::string, int>)> Comparator;
// Defining a lambda function to compare two pairs. It will compare two pairs using second field
Comparator compFunctor =
[](std::pair<std::string, int> elem1 ,std::pair<std::string, int> elem2)
{
return elem1.second < elem2.second;
};
// Declaring a set that will store the pairs using above comparision logic
std::set<std::pair<std::string, int>, Comparator> setOfWords(
mapOfWordCount.begin(), mapOfWordCount.end(), compFunctor);
// Iterate over a set using range base for loop
// It will display the items in sorted order of values
for (std::pair<std::string, int> element : setOfWords)
std::cout << element.first << " :: " << element.second << std::endl;
return 0;
}
別のマップを作成し、キーではない値に基づいてless()関数を提供します。また、value1 <= value2(厳密には<でない)の場合、関数はtrueを返す必要があります。この場合、異なる値を持つ要素もソートできます。