提案された使用法の範囲内でこれを行う必要がある場合 (カウンターをすばやく更新するためにキーマップを維持し、並べ替えられた結果をダンプする)、順序付けられていないマップとポインター ベクトルを使用する可能性があります。これにより、最初にいくつかのインデックス付きキー ソリューションが必要な主な理由は、カウントの更新時にデータ処理を大幅に高速化することであると想定しています。
言い換えれば、これを行うコードから適切なスピード バンプを得ようとしているということです。
++product[ id ]; // increment counter for product 'id' in our keyed-container.
ただし、ID ではなく、各 ID の累積カウントでソートされた出力をレポートすることはできます。そうは言っても、次の例は少し複雑ですが、まさにそれを行います。
#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <ctime>
#include <unordered_map>
#include <iterator>
#include <iomanip>
using namespace std;
int main(int argc, char *argv[])
{
typedef std::unordered_map<int, int> Products;
Products product;
// fill with random data for our test.
std::srand((unsigned)time(0));
for (int i=1;i<20;++i)
{
product[i] = rand() % 50 + 1;
cout << setw(3) << i << " ==> " << product[i] << endl;
}
cout << endl;
// now setup a one-shot sort. we're using a vector of
// pointers to our map value type
std::vector<const Products::value_type*> data;
data.reserve(product.size());
std::transform(product.begin(), product.end(), std::back_inserter(data),
[](const Products::value_type& obj) { return std::addressof(obj); });
// sort the vector by value (second)
std::stable_sort(data.begin(), data.end(),
[](const Products::value_type* left, const Products::value_type* right)
{ return left->second < right->second; });
// results are in the vector as pointers. the original map is unchanged.
for (auto ptr : data)
cout << setw(3) << ptr->first << " ==> " << ptr->second << endl;
return EXIT_SUCCESS;
};
サンプルラン
1 ==> 42
2 ==> 18
3 ==> 35
4 ==> 1
5 ==> 20
6 ==> 25
7 ==> 29
8 ==> 9
9 ==> 13
10 ==> 15
11 ==> 6
12 ==> 46
13 ==> 32
14 ==> 28
15 ==> 12
16 ==> 42
17 ==> 46
18 ==> 43
19 ==> 28
20 ==> 37
4 ==> 1
11 ==> 6
8 ==> 9
15 ==> 12
9 ==> 13
10 ==> 15
2 ==> 18
5 ==> 20
6 ==> 25
14 ==> 28
19 ==> 28
7 ==> 29
13 ==> 32
3 ==> 35
20 ==> 37
1 ==> 42
16 ==> 42
18 ==> 43
12 ==> 46
17 ==> 46
私は過去にこの方法を使用しました。これは、並べ替えのために一時的なコンテナーにコピーするのにコストがかかる、より複雑な構造の場合に非常に効率的であるためです。最後のポインタ ベクトルがマップ内の実際のデータを参照するということは、この特定の問題に対してはやり過ぎかもしれませんが、一般的な解決策として確かにメリットがあります。
そうは言っても、必要なのが int-to-int ダンプであり、マップ キーではなく second-int でソートされている場合、これも同様にうまくいきますが、最終目標を達成するためにコンテナーからデータをレプリケートします。 :
#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <ctime>
#include <unordered_map>
#include <iterator>
#include <iomanip>
using namespace std;
int main(int argc, char *argv[])
{
typedef std::unordered_map<int, int> Products;
Products product;
// fill with random data for our test.
std::srand((unsigned)time(0));
for (int i=1;i<20;++i)
{
product[i] = rand() % 50 + 1;
cout << setw(3) << i << " ==> " << product[i] << endl;
}
cout << endl;
// copy the values from the map to a sort bed.
std::vector<std::pair<int,int>> vals;
std::copy(product.begin(), product.end(), back_inserter(vals));
std::stable_sort(vals.begin(), vals.end(),
[](const std::pair<int,int>& left, const std::pair<int,int>& right)
{ return left.second < right.second; });
// dump to stdout
for (auto val : vals)
cout << setw(3) << val.first << " ==> " << val.second << endl;
return EXIT_SUCCESS;
}
サンプル出力
1 ==> 48
2 ==> 30
3 ==> 25
4 ==> 32
5 ==> 34
6 ==> 21
7 ==> 26
8 ==> 6
9 ==> 50
10 ==> 28
11 ==> 50
12 ==> 32
13 ==> 35
14 ==> 17
15 ==> 33
16 ==> 30
17 ==> 13
18 ==> 1
19 ==> 50
18 ==> 1
8 ==> 6
17 ==> 13
14 ==> 17
6 ==> 21
3 ==> 25
7 ==> 26
10 ==> 28
2 ==> 30
16 ==> 30
4 ==> 32
12 ==> 32
15 ==> 33
5 ==> 34
13 ==> 35
1 ==> 48
9 ==> 50
11 ==> 50
19 ==> 50