C++primer学習ノート——第十一章関連容器


関連コンテナと順序コンテナには根本的な違いがあります.関連コンテナの要素はキーワードで保存され、アクセスされます.これに対して、シーケンスコンテナの要素は、コンテナ内の場所によって順番に保存され、アクセスされます.
関連コンテナタイプ
キーワード順に要素を保存
map
≪関連配列|Association Array|ldap≫:キーワードの保存-値ペア
set
キーワードのみを保存するコンテナ
multimap
キーワードが繰り返されるmap
multiset
キーワードの繰り返し可能set
むじゅんしゅうごう
unordered_map
ハッシュ関数で組織されたmap
unordered_set
ハッシュ関数で組織されたset
unordered_multimap
ハッシュ関数で組織されたmap:キーワードが繰り返し表示されます
unordered_multiset
ハッシュ関数で組織されたset:キーワードが繰り返し表示されます
一、関連容器の使用
mapの使用
mapは、キーワード-値ペアのセットです.たとえば、名前-電話番号です.mapタイプは、通常、関連配列と呼ばれます.配列とは異なり、下付き文字は整数ではなく、位置ではなくキーワードで値を検索します.
map word_count;  //string size_t  map
string word;
while(cin>>word)
    ++word_count[word];        //  word        1
for(const auto &w:word_count)  
    cout<1)?"times":"time")<

whileサイクルでは、wordがmapに存在しない場合、下付き演算子は新しい要素を作成し、そのキーワードはwordで、値は0です.要素が新しく作成されたかどうかにかかわらず、値を1に加算します.
mapから要素を抽出するとpairタイプのオブジェクトが得られます.簡単に言えばpairはテンプレートタイプであり、firstとsecondという2つのデータメンバーを保存します.
setの使用
//              
map word_count;
set exclude={"The","But","And","Or","An","A"};
string word;
while(cin>>word)
    //     exclude    
    if(exclude.find(word)==exclude.end())
        ++word_count[word];

二、関連容器の概要
関連コンテナは、通常のコンテナ操作をサポートします.関連コンテナは、push_などのシーケンスコンテナの位置関連操作をサポートしていません.backまたはpush_front.また、関連コンテナは、1つの要素値と1つの数値を受け入れるコンストラクション関数または挿入操作をサポートしません.
関連コンテナの反復器は双方向です.
1、関連コンテナの定義
空のコンテナ+コピー初期化+範囲初期化+値初期化:
map word_count; //   
//     
set exclude={"the","but","and","or","an","a"};
//    ;authors      
map authors={{"Joyce","James"},
                            {"Austen","Jane"},{"Dickens","Charles"}};

コンテナmultimapとmultisetでは、複数の要素が同じキーワードを持つことができます.
2、キーワードタイプの要求
秩序化コンテナ、map、multimap、set、multisetの場合、キーワードタイプは要素の比較方法を定義する必要があります.デフォルトでは、標準ライブラリではキーワードタイプの
ソートアルゴリズムに渡される呼び出し可能なオブジェクトは、関連コンテナ内のキーワードと同じタイプの要件を満たす必要があります.
キーワードの厳密な弱順の代わりに、操作をカスタマイズできます.「以下」と見なすことができます.
実際のプログラミングでは、1つのタイプが「動作正常」を定義している場合に重要です.
キーワードタイプの比較関数の使用
キーワードタイプが自分で定義した操作を使用する場合は、関連コンテナタイプがこの操作を提供するタイプであることを定義する必要があります.すなわち、どのタイプのコンテナを定義するかをカッコで指定し、カスタム操作はエレメントタイプに続くカッコで指定する必要があります.
bookstoreオブジェクトをcompareIsbnで初期化します.これは、bookstoreに要素を追加すると、compareIsbnを呼び出してこれらの要素をソートすることを意味します.
bool  compareIsbn(const Sales_data &lhs,const Sales_data &rhs)
{
    return lhs.isbn()
    bookstore(compareIsbn);   

3、pairタイプ
pairタイプ定義はヘッダファイルutilityにあります
pair上の操作
pair p;
pはpairであり、値の初期化を行う
pair p(v1,v2);
v 1とv 2でpを初期化する
pair p={v1,v2};
p(v 1,v 2)に等価である.
make_pair(v1,v2)
v 1とv 2で初期化されたpairを返します.pairのタイプはv 1とv 2のタイプから推定される
p.first
pを返すfirstデータメンバー(共通)
p.second
pのsecondデータメンバー(共有)を返します.
p1 relop p2
リレーショナル演算子(<><=>=)はディクショナリ順に定義されます.
p1==p2
firstとsecondメンバーがそれぞれ等しい場合、2つのpairは等しい
p1!=p2
pairオブジェクトを作成する関数
pair
process(vector &v)
{
    if(!v.empty())
        //      pair     
        return {v.back(),v.back().size()}; //     
        return pair(v.back(),v.back().size());
        return make_pair(v.back(),v.back().size());
    else
        return pair(); //         
}

三、関連コンテナ操作
関連コンテナの追加タイプ別名
key_type
このコンテナタイプのキーワードタイプ
mapped_type
各キーワードに関連付けられたタイプ;mapのみに適用
value_type
setの場合key_typeはmapに対してpairである
1、関連コンテナ反復器
関連するコンテナ反復器を参照すると、コンテナのvalue_というタイプが得られます.typeの値の参照.
覚えておいてくださいmapのvalue_typeはpairでpairの値を変更できますが、キーワードメンバーの値を変更することはできません.
auto map_it=word_count.begin();
//*map_it     pair     
cout<first;
cout<second;
map_it->first="new_key";     //  :    const 
++map_it->second;            //  :           

setの反復器はconstです
1つのsetのキーワードもconstで、1つのset反復器で要素の値を読み取ることができますが、変更できません.
関連コンテナを巡回
反復器を使用してmap、multimap、set、またはmultisetを巡回すると、反復器はキーワードの昇順に要素を巡回します.
関連コンテナとアルゴリズム
一般的には、関連コンテナに汎用アルゴリズムを使用しません.キーワードはconstという特性のため、コンテナに対して修正や並べ替えのアルゴリズムを使用できません.また、関連するコンテナの要素はキーワードで検索できません.そのため、汎用検索アルゴリズムを使用するのは悪い考えです.
実際のプログラミングでは、関連するコンテナにアルゴリズムを使用する場合は、ソースシーケンスとして使用するか、目的の場所として使用します.
2、要素の追加
関連コンテナのinsert操作
c.insert(v)
mapおよびsetの場合、要素のキーワードがcにない場合にのみ要素を挿入(構築)します.関数はpairを返し、指定したキーワードを持つ要素を指す反復器と、挿入に成功したかどうかを示すbool値を含む.Multimapとmultisetの場合、指定した要素が常に挿入(構築)され、新しい要素を指す反復器が返されます.
c.emplace(args)
c.insert(b,e)
関数は、mapおよびsetのvoidを返し、要素のキーワードがcにない場合にのみ要素を挿入(構築)します.Multimapとmultisetの場合、常に範囲内の各要素を挿入(構築)します.
c.insert(il)
c.insert(p,v)
指定した要素に要素を挿入し、指定したキーワードを持つ要素を指す反復器を返します.
c.emplace(p,args)
mapに要素を追加
// word_count  word 4   
word_count.insert({word,1});
word_count.insert(pair(word,1));
word_count.insert(make_pair(word,1));
word_count.insert(map::value_type(word,1));

Insertの戻り値の検出
キーワードがすでにコンテナにある場合、insertは何もしなくてもよく、戻り値のbool部分はfalseです.キーワードが存在しない場合、要素はコンテナに挿入され、bool値はtrueになります.
//                       
map word_count;
string word;
while(cin>>word)
{
    //ret->first          ,  pair, ++ret->first.second      
    auto ret=word_count.insert({word,1});
    if(!ret->second)
          ++ret->first.second;  
    
}

ret--pairタイプ::iterator,bool>
ret.first-map反復器で、指定したキーワードを持つ要素を指します.
ret.first->--pairです.
ret.first->second-mapの要素の値部分
++ret.first->second-この値を増加
 
Multisetまたはmultimapに要素を追加
multiコンテナ内のキーワードが一意である必要がないため、これらのタイプではinsertを使用して要素が挿入されます.したがって、単一の要素のinsert操作を受け入れると、bool値を返す必要がなく、新しい要素を指す反復器が返されます.
multimap  authors;
authors.insert({ "Barth,Jhon","Sot-Weet Factor" });
authors.insert({ "Barth,Jhon","Lost in the Funhouse" });

3、要素の削除
関連コンテナから要素を削除
c.erase(k)
各キーワードがkの要素を削除します.size_を返しますtype値、削除された要素の数を示す
c.erase(p)
反復器pで指定した要素を削除し、pの後の要素を指す反復器を返します.
c.erase(b,e)
反復器bとeが表す範囲の要素を削除します.eを返す
4、mapの下付き操作
mapとunordered_mapの下付き操作
c[k]
キーワードkの要素を返します.kがcにない場合は、キーワードkの要素を追加し、値を初期化します.
c.at(k)
アクセスキーワードkの要素は、パラメータチェック付きです.kがcになければout_を投げ出すof_range異常
setタイプでは、setにキーワードに関連付けられた「値」がないため、下付き文字はサポートされません.
Multimapとundered_maltimapは、これらのコンテナに複数の値がキーワードに関連付けられている可能性があるため、下付き操作をサポートしません.
下付き演算子は新しい要素を挿入する可能性があるため、const以外のmapに対して下付き演算子を使用するしかありません.
下付き操作の戻り値の使用
vectorとstringとは異なり、mapの下付き演算子が返すタイプは、map反復器を参照して得られるタイプとは異なります.
1つのmapに対して下付き操作を行うと、1つのmapped_が得られます.type(p.second)オブジェクトですが、map反復器を参照するとvalue_が得られます.typeオブジェクト(pair).
5、要素へのアクセス
関連コンテナで要素を検索する操作
lower_boundとupper_boundは無秩序容器の下付きスケールとat操作には適用されません.非constのmapとunordered_にのみ適用されます.map(下付き操作に対応するキーワードがない場合、要素が追加されます)
c.find(k)
最初のキーワードがkの要素を指す反復器を返します.
c.count(k)
キーワードkを返す要素の数
c.lower_bound(k)
最初のキーワードがkより小さくない要素を指す反復器を返します.
c.upper_bound(k)
最初のキーワードがkより大きい要素を指す反復器を返します.
c.equal_range(k)
キーワードがkに等しい要素の範囲を表すpairを返します.kが存在しない場合、pairの2つのメンバーはc.end()に等しい.
set iset={0,1,2,3,4,5,6,7,8,9};\
iset.find(1); //    key==1    
iset.find(11); //  iset.end()
iset.count(1); //  1
iset.count(11); //  0

下付き操作の代わりにmapにfindを使用する
場合によっては、mapを変更するのではなく、特定のキーワードがmapにあるかどうかを知りたいだけです.findを使用する必要があります.
if(word_count.find("foobar")==word_count.end())
    cout<

Multimapまたはmultisetで要素を検索する
コンテナには、指定されたキーワードを持つ要素がたくさんある場合があります.1つのmultimapまたはmultisetの複数の要素に所定のキーワードがある場合、これらの要素はコンテナに隣接して格納されます.
次に、ある著作者から著作テーマへのマッピングで、特定の著作者のすべての著作を印刷します.
//        
//     
string search_item("Alain de Botton");  //      
auto entries=authors.count(search_item);    //     
auto iter=authors.find(search_item);        //     
while(entries){
    cout<second<second<second<

6、単語変換のmap
#include
#include
#include
#include
#include
#include

using namespace std;

const string &transform(const string &s, const map &m)
{
	auto map_it = m.find(s);
	if (map_it != m.end())
		return map_it->second;
	else
		return s;
}

map buildMap(ifstream &map_file)
{
	map trans_map;
	string key;
	string value;
	while (map_file >> key && getline(map_file, value))
		if (value.size() > 1)
			trans_map[key] = value.substr(1);
		else
			throw runtime_error("no rule for "+ key);
	return trans_map;
}

void word_transform(ifstream &map_file, ifstream &input)
{
	auto trans_map = buildMap(map_file);
	string text;
	while (getline(input, text))
	{
		istringstream stream(text);
		string word;
		bool firstword = true;
		while (stream >> word)
		{
			if (firstword)
				firstword = false;
			else
				cout << " ";
			cout << transform(word,trans_map);
		}
		cout << endl;
	}
}
int main()
{
	ifstream mapfile("map_file.txt");
	ifstream input("input.txt");
	word_transform(mapfile,input);

	return 0;

}