2011-02-07 23 views
0

私は入力の行を読み取るこの小さなプログラムを持っています&は、その中の単語を、それぞれの出現数で出力します。私は、それらの出現に応じてこれらの値を格納するマップ内の要素を並べ替える必要があります。つまり、一度しか出現しない言葉は、最初に出てくるように命じられ、次に2回目に出現する言葉が7回ほど続きます。私は、述語がブール値を返す必要があることを知っていますが、パラメータがどうあるべきかわかりません。マップの2つのイテレータでなければなりませんか?これを説明できる人がいれば、大いに感謝します。前もって感謝します。文字列から文字列へのマップの述語

#include<iostream> 
#include<map> 

using std::cout; 
using std::cin; 
using std::endl; 
using std::string; 
using std::map; 

int main() 
{ 
    string s; 
    map<string,int> counters; //store each word & an associated counter 

    //read the input, keeping track of each word & how often we see it 
    while(cin>>s) 
    { 
     ++counters[s]; 
    } 

    //write the words & associated counts 
    for(map<string,int>::const_iterator iter = counters.begin();iter != counters.end();iter++) 
    { 
     cout<<iter->first<<"\t"<<iter->second<<endl; 
    } 

    return 0; 
} 

答えて

7

std::mapは、常にそのキーに従ってソートされます。要素を値でソートすることはできません。

ソート可能な別のデータ構造(たとえばstd::vector<std::pair<string, int> >)に内容をコピーする必要があります。

このような並べ替えに使用できる述語はvectorです。 C++標準ライブラリのソートアルゴリズムでは、基本的に「より小さい」という述語が「より小さい」必要があることに注意してください。

bool cmp(std::pair<string, int> const &a, std::pair<string, int> const &b) { 
    return a.second < b.second; 
} 
+2

私はそれを行うための簡潔な構文があることを追加します: 'のstd ::ベクトル<はstd ::ペア> V(counters.begin()、counters.end()) ; ' –

+0

これは、マップには述語がないことを意味しますか?もしこれが愚かな質問なら私を許してください、私はまだ学生です。 – Ramila

+0

std :: mapに型パラメーターとして述部を与えることはできますが、その述部は値ではなくキーをソートするために使用されます。 std :: mapはソート述部を必要とするので、高速検索が可能です。 – hrnt

0

あなたはstd::mapとワンパスでこれを行うことができるようにするつもりはありません。一度に1つだけソートすることができ、その場でキーを変更することはできません。私がお勧めするのは、countersマップを維持するコードを使用してから、std::max_elementと、マップ内の各std::pair<string, int>secondフィールドを比較する比較関数を使用することです。

1

マップを作成することはできません。マップの順序はあらかじめ定義されています(デフォルトでは、キータイプのstd::less)。あなたの問題の最も簡単な解決策は、std::multimap<int, string>を作成し、そこに値を挿入してから、キータイプ(int、発生数)で並べ替えられたマルチマップをループするだけです。述語を定義する必要はありません。

0

マップのキーはその値ではなくソートされています。それがマップを効率的にする理由です。

0

前述したように、マップは常に動作しません。マップは常にキー値(文字列)でソートされたままです。

他の人が指摘しているように、データを他の構造体にコピーして値で並べ替えることができます。もう1つの可能性は、代わりにBoost bimapを使用することです。以前は基本的な考え方のdemoを投稿しました。

0

おそらくmap<string,int>vector<pair<const string, int> >に変換し、intメンバーのベクターを並べ替えることができます。あなたは

struct PairLessSecond 
{ 
    template< typename P > 
    bool operator()(const P& pairLeft, const P& pairRight) const 
    { 
    return pairLeft.second < pairRight.second; 
    } 
}; 

を行うことができ

あなたはおそらくもバインドして、ラムダを使って何とかこのすべてを構築することができます。

std::vector< std::map<std::string,int>::value_type > byCount; 
    std::sort(byCount.begin(), byCount.end(), PairLessSecond());