c++迭代器提取map key_C++(STL):29 關聯式容器map 迭代器
技術標籤:c++迭代器提取map key
無論是前面學習的序列式容器,還是關聯式容器,要想實現遍歷操作,就必須要用到該型別容器的迭代器。當然,map 容器也不例外。
C++STL標準庫為 map 容器配備的是雙向迭代器(bidirectional iterator)。這意味著,map 容器迭代器只能進行 ++p、p++、--p、p--、*p 操作,並且迭代器之間只能使用 == 或者 != 運算子進行比較。
值得一提的是,相比序列式容器,map 容器提供了更多的成員方法(如表 1 所示),通過呼叫它們,我們可以輕鬆獲取具有指定含義的迭代器。
成員方法 | 功能 |
---|---|
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 所示。
圖 2 表 1 部分成員方法的功能示意圖
注意,圖中 Ei表示的是 pair 類物件,即鍵值對。對於 map 容器來說,每個鍵值對的鍵的值都必須保證是唯一的。
下面程式以 begin()/end() 組合為例,演示瞭如何遍歷 map 容器:
#include
#include // pair
#include // string
using 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 // string
using 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 容器,預設會根據各鍵值對中鍵的值,對各鍵值對做升序排序,其排序的結果為:
在此基礎上,通過呼叫 find() 方法,我們可以得到一個指向鍵為 "Java教程" 的鍵值對的迭代器,由此當使用for 迴圈從該迭代器出開始遍歷時,就只會遍歷到最後 2 個鍵值對。
同時,map 類模板中還提供有 lower_bound(key) 和 upper_bound(key) 成員方法,它們的功能是類似的,唯一的區別在於:
lower_bound(key) 返回的是指向第一個鍵不小於 key 的鍵值對的迭代器;
upper_bound(key) 返回的是指向第一個鍵大於 key 的鍵值對的迭代器;
下面程式演示了它們的功能:
#include
#include // pair
#include // string
using 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 // string
using 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 個鍵值對。