2013-04-28 29 views
7

Tôi đang sử dụng std :: bản đồ theo cách như vậy:C++ std :: map <std :: string, int> nhận giá trị mà bắt đầu quan trọng với một chuỗi đặc biệt

#include <map> 
#include <string> 
#include <iostream> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    map<string, int> my_map; 

    my_map.insert(pair<string, int>("Ab", 1)); 
    my_map.insert(pair<string, int>("Abb", 2)); 
    my_map.insert(pair<string, int>("Abc", 3)); 
    my_map.insert(pair<string, int>("Abd", 4)); 
    my_map.insert(pair<string, int>("Ac", 5)); 
    my_map.insert(pair<string, int>("Ad", 5)); 

    cout<<my_map.lower_bound("Ab")->second<<endl; 
    cout<<my_map.upper_bound("Ab")->second<<endl; 
    return 0; 
} 

http://ideone.com/5YPQmj

Tôi muốn nhận tất cả các giá trị có khóa bắt đầu bằng một chuỗi cụ thể (ví dụ: "Ab"). Tôi có thể dễ dàng có được trình lặp bắt đầu sử dụng bản đồ :: lower_bound. Nhưng làm thế nào tôi có thể nhận được một ràng buộc trên? Tôi có phải lặp lại toàn bộ thiết lập bắt đầu từ giới hạn dưới và kiểm tra mọi khóa nếu nó vẫn bắt đầu bằng "Ab"?

+2

Trong trường hợp cụ thể này 'my_map.lower_bound (" Ac ")' có vẻ như vậy –

+0

Tại sao không bị ràng buộc cho "Ac"? không có chữ cái giữa b và c. – stardust

+0

Tôi cần cách tiếp cận tổng quát hơn. Ví dụ chỉ để mô tả vấn đề. Tôi có thể là bất kỳ loại chuỗi nào và bản đồ có thể chứa bất kỳ loại chuỗi nào. – Dejwi

Trả lời

1

Tôi tìm thấy một câu trả lời tương tự như kiểm tra trang này: (map complex find operation)

Mã gây:

template<typename Map> typename Map::const_iterator 
find_prefix(Map const& map, typename Map::key_type const& key) 
{ 
    typename Map::const_iterator it = map.upper_bound(key); 
    while (it != map.begin()) 
    { 
     --it; 
     if(key.substr(0, it->first.size()) == it->first) 
      return it; 
    } 

    return map.end(); // map contains no prefix 
} 

Có vẻ như trong ví dụ này, bạn lặp từ UPPER_BOUND ngược đến đầu tìm kiếm chuỗi con cụ thể

Ví dụ này hơi khác một chút nhưng phải là máy chủ làm khối xây dựng tốt

+0

Bạn có thể cần phải đề cập rằng đây là một giải pháp không tối ưu và một cơ sở hạ tầng khác là theo thứ tự. – sehe

1
class BeginWithKey 
{ 
public: 
    BeginWithKey(const string key); 
    bool operator()(const string& s,const int x); 
private: 
    const string& key_; 
}; 

BeginWithKey::BeginWithKey(const string key):key_(key) 
{ 
} 

bool BeginWithKey::operator()(const string& s, const int& rh) 
{ 
    bool begin = true; 

    for(int i = 0; i < key_.size() && begin; ++i) 
     begin = (s[i] == key_[i]); 
    return !begin; 
} 

int main() 
{ 
    //your code 

    //copying the map object 
    map<string, int> copy = my_map; 

    //removing the strings not beginning with abc 
    BeginWithKey func("abc"); 
    remove_if(copy.begin(), copy.end(), func); 

    return 0; 
} 

Mã sẽ hoạt động với bất kỳ khóa chuỗi nào.

1

bạn có thể sử dụng Boost filter iterator mà cung cấp cho bạn một "bắt đầu" và "kết thúc" lặp từ lặp bình thường khi họ cho một vị (một hàm bool mà nói đó giá trị bao gồm)

Ví dụ:

template <class Predicate> 
boost::filter_iterator<Predicate, map<string,int>::const_iterator> begin(Predicate predicate) const 
{ 
    return boost::make_filter_iterator(predicate, my_map.begin(), my_map.end()); 
} 
template <class Predicate> 
boost::filter_iterator<Predicate, map<string,int>::const_iterator> end(Predicate predicate) const 
{ 
    return boost::make_filter_iterator(predicate, my_map.end(), my_map.end()); 
} 

struct isMatch 
{ 
    isMatch(const std::string prefix) {m_prefix = prefix;}; 
    bool operator()(std::string value) 
    { 
     return value.find_first_of(m_prefix) == 0; 
    }; 
    std::string m_prefix; 
}; 

//using: 
isMatch startWithAb("Ab"); 
auto myBegin = boost::filter_iterator<startWithAb> begin(); 
auto myEnd = boost::filter_iterator<startWithAb> end(); 
Các vấn đề liên quan