web-dev-qa-db-ja.com

値でSTLマップをソートするにはどうすればよいですか?

値でソートする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

この方法でマップを並べ替えるにはどうすればよいですか?キーと値をソートされた値で処理できる方法はありますか?

48
Charlie Epps

最初のマップの値をキーとして、最初のマップのキーを値として、2番目のマップを作成できます。

これは、すべての値が異なる場合にのみ機能します。これを想定できない場合は、マップの代わりにマルチマップを構築する必要があります。

30
swegi

すべてのキーと値のペアを最初にset<pair<K, V> >にダンプします。ここで、setは、ペアの2番目の値のみを比較するより小さいファンクターで構築されます。そうすれば、値がすべて異なっていなくてもコードは機能します。

または、キーと値のペアをvector<pair<K, V> >にダンプし、その後、そのベクトルを同じより小さいファンクターでソートします。

61

値でソートするSTLマップをどのように実装できますか。

できません、定義による。マップは、キーで要素を並べ替えるデータ構造です。

16
Konrad Rudolph

このようなことには Boost.Bimap を使用する必要があります。

4
rlbond

@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

1
honk

私はちょうど私の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;
}
1
hatethisgarbage

私はこれを 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;
}
0
Pat. ANDRIA

別のマップを作成し、キーではない値に基づいてless()関数を提供します。また、value1 <= value2(厳密には<でない)の場合、関数はtrueを返す必要があります。この場合、異なる値を持つ要素もソートできます。

0
Hua Zhong