2011-02-07 39 views
0

我有這個讀取輸入行&的小程序打印其中的單詞以及它們各自的出現次數。我想根據它們的出現對地圖中存儲這些值的元素進行排序。我的意思是,只出現一次的單詞將被命令在開頭,然後是出現兩次的單詞等等。我知道謂詞應該返回一個bool值,但我不知道參數應該是什麼。它應該是兩個迭代器到地圖嗎?如果有人能解釋這一點,將不勝感激。先謝謝你。從字符串到int的映射的謂詞

#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++標準庫中的排序算法需要一個「小於」謂詞,它基本上表示「比b小」。

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

我將添加有一個簡明的語法要做到這一點:`的std ::矢量<性病::對> V(counters.begin(),counters.end()) ;` – 2011-02-07 15:37:27

0

你不能用一個通過std::map做到這一點。它一次只能按一件事分類,而且你不能原地更換鑰匙。我建議使用現在的代碼來維護counters地圖,然後使用std::max_element並使用比較功能,比較地圖中每個std::pair<string, int>second字段。

1

您無法使用地圖,它的順序是預定義的(默認情況下,從鍵盤上的std::less)。對於你的問題最容易的解決方案是創建一個std::multimap<int, string>並在那裏插入你的值,然後循環遍歷multimap,它將按照鍵類型(int,發生次數)進行排序,這會給你命令你不需要定義一個謂詞。

0

地圖的按鍵排序,而不是其值。這就是使地圖高效的原因。如果沒有使用其他數據結構(可能是反向索引),則無法對其進行排序(可能是反向索引!)

0

如上所述,它根本無法工作 - 地圖始終保持按鍵值排序,這將是字符串。

正如其他人所指出的,您可以將數據複製到其他結構中,然後按值排序。另一種可能性是使用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; 
    } 
}; 

你或許可以也構建這一切都以某種方式使用帶有綁定一個lambda。

現在

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