1. 程式人生 > 其它 >c++迭代器提取map key_C++(STL):29 關聯式容器map 迭代器

c++迭代器提取map key_C++(STL):29 關聯式容器map 迭代器

技術標籤:c++迭代器提取map key

無論是前面學習的序列式容器,還是關聯式容器,要想實現遍歷操作,就必須要用到該型別容器的迭代器。當然,map 容器也不例外。
C++STL標準庫為 map 容器配備的是雙向迭代器(bidirectional iterator)。這意味著,map 容器迭代器只能進行 ++p、p++、--p、p--、*p 操作,並且迭代器之間只能使用 == 或者 != 運算子進行比較。
值得一提的是,相比序列式容器,map 容器提供了更多的成員方法(如表 1 所示),通過呼叫它們,我們可以輕鬆獲取具有指定含義的迭代器。

表 1 map 容器迭代器相關成員方法
成員方法功能
begin()返回指向容器中第一個(注意,是已排好序的第一個)鍵值對的雙向迭代器。如果 map 容器用 const 限定,則該方法返回的是 const 型別的雙向迭代器。
end()返回指向容器最後一個元素(注意,是已排好序的最後一個)所在位置後一個位置的雙向迭代器,通常和 begin() 結合使用。如果 map 容器用 const 限定,則該方法返回的是 const 型別的雙向迭代器。
rbegin()返回指向最後一個(注意,是已排好序的最後一個)元素的反向雙向迭代器。如果 map 容器用 const 限定,則該方法返回的是 const 型別的反向雙向迭代器。
rend()返回指向第一個(注意,是已排好序的第一個)元素所在位置前一個位置的反向雙向迭代器。如果 map 容器用 const 限定,則該方法返回的是 const 型別的反向雙向迭代器。
cbegin()和 begin() 功能相同,只不過在其基礎上,增加了 const 屬性,不能用於修改容器記憶體儲的鍵值對。
cend()和 end() 功能相同,只不過在其基礎上,增加了 const 屬性,不能用於修改容器記憶體儲的鍵值對。
crbegin()和 rbegin() 功能相同,只不過在其基礎上,增加了 const 屬性,不能用於修改容器記憶體儲的鍵值對。
crend()和 rend() 功能相同,只不過在其基礎上,增加了 const 屬性,不能用於修改容器記憶體儲的鍵值對。
find(key)在 map 容器中查詢鍵為 key 的鍵值對,如果成功找到,則返回指向該鍵值對的雙向迭代器;反之,則返回和 end() 方法一樣的迭代器。另外,如果 map 容器用 const 限定,則該方法返回的是 const 型別的雙向迭代器。
lower_bound(key)返回一個指向當前 map 容器中第一個大於或等於 key 的鍵值對的雙向迭代器。如果 map 容器用 const 限定,則該方法返回的是 const 型別的雙向迭代器。
upper_bound(key)返回一個指向當前 map 容器中第一個大於 key 的鍵值對的迭代器。如果 map 容器用 const 限定,則該方法返回的是 const 型別的雙向迭代器。
equal_range(key)該方法返回一個 pair 物件(包含 2 個雙向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等價,pair.second 和 upper_bound() 方法的返回值等價。也就是說,該方法將返回一個範圍,該範圍中包含的鍵為 key 的鍵值對(map 容器鍵值對唯一,因此該範圍最多包含一個鍵值對)。


表 1 中多數的成員方法,諸如 begin()、end() 等,在學習序列式容器時已經多次使用過,它們的功能如圖 2 所示。

f7df8678a7d3f346df2e249196b4e9ff.png
圖 2 表 1 部分成員方法的功能示意圖

注意,圖中 Ei表示的是 pair 類物件,即鍵值對。對於 map 容器來說,每個鍵值對的鍵的值都必須保證是唯一的。

下面程式以 begin()/end() 組合為例,演示瞭如何遍歷 map 容器:

#include #include       // pair#include        // stringusing namespace std;int main() {  //建立並初始化 map 容器  std::map<std::string, std::string>myMap{ {"player_01","player_data"},{"player_02","player_data"} };  //呼叫 begin()/end() 組合,遍歷 map 容器  for (auto iter = myMap.begin(); iter != myMap.end(); ++iter) {    cout << iter->first << " " << iter->second << endl;  }  return 0;}

程式執行結果為:

player_01 player_data

player_02 player_data

讀者可自行嘗試使用其他組合(如 cbegin()/cend()、 rbegin()/rend() 等)遍歷 map 容器。


除此之外,map 類模板中還提供了 find() 成員方法,它能幫我們查詢指定 key 值的鍵值對,如果成功找到,則返回一個指向該鍵值對的雙向迭代器;反之,其功能和 end() 方法相同。
舉個例子:

#include #include       // pair#include        // stringusing namespace std;int main() {  //建立並初始化 map 容器  std::map<std::string, std::string>myMap{ {"player_01","player_data"},{"player_02","player_data"} };  //呼叫 begin()/end() 組合,遍歷 map 容器  auto ite = myMap.find("player_01");  if (ite != myMap.end()) {    cout << ite->second << endl;  }  return 0;}

程式執行結果為:

player_data


此程式中,建立並初始化的 myMap 容器,預設會根據各鍵值對中鍵的值,對各鍵值對做升序排序,其排序的結果為:

0ea997b1e561825b7d797c518db135b5.png

在此基礎上,通過呼叫 find() 方法,我們可以得到一個指向鍵為 "Java教程" 的鍵值對的迭代器,由此當使用for 迴圈從該迭代器出開始遍歷時,就只會遍歷到最後 2 個鍵值對。
同時,map 類模板中還提供有 lower_bound(key) 和 upper_bound(key) 成員方法,它們的功能是類似的,唯一的區別在於:

  • lower_bound(key) 返回的是指向第一個鍵不小於 key 的鍵值對的迭代器;

  • upper_bound(key) 返回的是指向第一個鍵大於 key 的鍵值對的迭代器;


下面程式演示了它們的功能:

#include #include       // pair#include        // stringusing namespace std;int main() {  //建立並初始化 map 容器  std::map<std::string, std::string>myMap{ {"player_01","player_data"},{"player_02","player_data"} };  //呼叫 begin()/end() 組合,遍歷 map 容器  auto iter = myMap.lower_bound("player_01");  if (iter != myMap.end()) {    cout << "lower:" << iter->first << " " << iter->second << endl;  }    //找到第一個鍵的值大於 "Java教程" 的鍵值對  iter = myMap.upper_bound("player_02");  if (iter != myMap.end()) {    cout << "upper:" << iter->first << " " << iter->second << endl;  }  return 0;}


equal_range(key) 成員方法可以看做是 lower_bound(key) 和 upper_bound(key) 的結合體,該方法會返回一個 pair 物件,其中的 2 個元素都是迭代器型別,其中 pair.first 實際上就是 lower_bound(key) 的返回值,而 pair.second 則等同於 upper_bound(key) 的返回值。
顯然,equal_range(key) 成員方法表示的一個範圍,位於此範圍中的鍵值對,其鍵的值都為 key。舉個例子:

#include #include       // pair#include        // stringusing namespace std;int main() {  //建立並初始化 map 容器  std::map<std::string, std::string>myMap{ {"player_01","player_data"},{"player_03","player_data"} };  //呼叫 begin()/end() 組合,遍歷 map 容器  //建立一個 pair 物件,來接收 equal_range() 的返回值  pair <std::map<string, string>::iterator, std::map<string, string>::iterator> myPair = myMap.equal_range("player_01");  //通過遍歷,輸出 myPair 指定範圍內的鍵值對  for (auto iter = myPair.first; iter != myPair.second; ++iter) {    cout << iter->first << " " << iter->second << endl;  }  return 0;}

程式執行結果為:

player_01 player_data

和 lower_bound(key)、upper_bound(key) 一樣,該方法也更常用於 multimap 容器,因為 map 容器中各鍵值對的鍵的值都是唯一的,因此通過 map 容器呼叫此方法,其返回的範圍內最多也只有 1 個鍵值對。