私の前のすべての答えは本当に答えを与えませんでした。
考えられる解決策について考えてみましょう。
コンテナ内の何かを数えるための多かれ少なかれ標準的なアプローチがあります。
std::map
aや。のような連想コンテナを使用できますstd::unordered_map
。そしてここで、「キー」(この場合は単語)をカウント(この場合は特定の単語のカウント)に関連付けます。
そして幸いなことに、マップには非常に優れたインデックスがありますoperator[]
。これにより、指定されたキーが検索され、見つかった場合は、値への参照が返されます。見つからない場合は、キーを使用して新しいエントリを作成し、新しいエントリへの参照を返します。したがって、どちらの場合も、カウントに使用される値への参照を取得します。そして、私たちは簡単に書くことができます:
std::unordered_map<char,int> counter{};
counter[word]++;
そして、それは本当に直感的に見えます。
この操作の後、度数分布表はすでに作成されています。キー(単語)でソートするか、std::map
またはを使用してソートしますが、。を使用するとより高速にアクセスできますstd::unordered_map
。
次に、頻度/カウントに従って並べ替えます。残念ながら、これはマップでは不可能です。
std::sort
したがって、 `` `std :: vector`````のような2番目のコンテナーを使用する必要があります。これにより、任意の述語に対してunsingを並べ替えることができます。または、std::multiset
暗黙的に順序付けするようなコンテナーに値をコピーできます。その要素。
aの単語を取得するには、 aと標準の抽出演算子をstd::string
使用します。大したことはありません。std::istringstream
>>
また、stdコンテナにこのような長い名前をすべて書き込むため、using
キーワードを使用してエイリアス名を作成します。
この後、超コンパクトなコードを記述し、数行のコードでタスクを実行します。
#include <iostream>
#include <string>
#include <sstream>
#include <utility>
#include <set>
#include <unordered_map>
#include <type_traits>
#include <iomanip>
// ------------------------------------------------------------
// Create aliases. Save typing work and make code more readable
using Pair = std::pair<std::string, unsigned int>;
// Standard approach for counter
using Counter = std::unordered_map<Pair::first_type, Pair::second_type>;
// Sorted values will be stored in a multiset
struct Comp { bool operator ()(const Pair& p1, const Pair& p2) const { return (p1.second == p2.second) ? p1.first<p2.first : p1.second>p2.second; } };
using Rank = std::multiset<Pair, Comp>;
// ------------------------------------------------------------
std::istringstream text{ " 4444 55555 1 22 4444 333 55555 333 333 4444 4444 55555 55555 55555 22 "};
int main() {
Counter counter;
// Count
for (std::string word{}; text >> word; counter[word]++);
// Sort
Rank rank(counter.begin(), counter.end());
// Output
for (const auto& [word, count] : rank) std::cout << std::setw(15) << word << " : " << count << '\n';
}