2012-09-07 40 views
7

Tôi có một số mã (đang hoạt động) sử dụng số multimap<string,string>. Tôi muốn thay đổi nó để không cho phép các giá trị trùng lặp trên cùng một khóa (rõ ràng là các giá trị khác nhau trên cùng một khóa là tốt, nếu không tôi sẽ không sử dụng một multimap).Làm thế nào để tránh các cặp trùng lặp/tìm thấy một cặp trong multimap?

Đáng ngạc nhiên là loại không seem để có cách tích hợp để tránh trùng lặp hoặc không tìm cặp khóa-giá trị (chỉ để tìm khóa). Nhưng tôi tìm một ai đó trên SO phải có cách giải quyết sẵn sàng. Bất kỳ ai?

+0

Giá trị trùng lặp có được phép có các khóa khác nhau không? Bạn dự định sử dụng bao nhiêu chìa khóa nhiều lần và tần suất đó bao nhiêu lần? – ypnos

+0

Chắc chắn, cùng một giá trị trên các phím khác nhau là tốt. Trong trường hợp của tôi các fan-out là nhỏ (thường là 1 hoặc 2 giá trị cho mỗi khóa) vì vậy đề nghị của DeadMG để chuyển sang 'std :: map >' không hiệu quả hoặc thuận tiện (vì multimap mã dựa trên đã được viết). – Qwertie

Trả lời

3

Đây là những gì tôi đã đưa ra:

template<class K, class V> 
typename multimap<K, V>::const_iterator find_pair(const multimap<K, V>& map, const pair<K, V>& pair) 
{ 
    typedef multimap<K, V>::const_iterator it; 
    std::pair<it,it> range = map.equal_range(pair.first); 
    for (it p = range.first; p != range.second; ++p) 
     if (p->second == pair.second) 
      return p; 
    return map.end(); 
} 
template<class K, class V> 
bool insert_if_not_present(multimap<K, V>& map, const pair<K, V>& pair) 
{ 
    if (find_pair(map, pair) == map.end()) { 
     map.insert(pair); 
     return true; 
    } 
    return false; 
} 

(Đây không phải là hiệu quả khi có một số lượng lớn các giá trị gắn liền với một chìa khóa duy nhất, nhưng trong trường hợp của tôi có rất ít giá trị trên mỗi phím.)

+0

Nếu điều duy nhất bạn sử dụng trình lặp lại được trả về để so sánh, thì tại sao không chỉ trả về 'bool' thay thế? – jrok

+0

Bởi vì ai biết được, tôi có thể muốn 'map.erase (find_pair (...))' một ngày nào đó. Một wrapper contains_pair() cũng có thể có ích, thừa nhận. – Qwertie

1

Đề xuất của tôi cho bạn sẽ là bọc nhiều ảnh trong một lớp và chỉ cần thực hiện xác minh trong phương thức mà bạn thêm nội dung nào đó vào bản đồ. Phần còn lại của các hàm sẽ đơn giản đi qua các phương thức của multimap. Nó làm cho rất nhiều mã tấm nồi hơi nhưng nếu bạn cần phải làm các loại xác minh khác, nó sẽ dễ dàng hơn theo cách này.

+0

Đề xuất của bạn sẽ là thời gian O (N). – Puppy

0

Dường như

 std::set<std::pair<std::string,std::string>>> 

sẽ có chính xác các thuộc tính bạn đang tìm kiếm.

Tuy nhiên, đó không phải là bản đồ cũng không phải là nhiều ảnh. Bạn có thể giữ cho cả hai multimap và tập hợp các cặp khóa, giá trị hoặc tạo bộ này để chỉ kiểm tra tính nhất quán.

Tôi sẽ sử dụng bộ này và tạo bộ điều hợp trên giao diện đa phương thức. Có lẽ nó không phải là giải pháp dễ nhất để thực hiện, nhưng với hiệu quả hoạt động tốt nhất.

Xem câu hỏi "mẫu thiết kế bộ điều hợp" để tham khảo.


[UPDATE]

Xem tôi working example như là một điểm khởi đầu.

Ví dụ: làm thế nào để lặp qua tất cả các giá trị cho phím - xem:

typedef std::set<std::pair<std::string, std::string> > ssset; 

ssset::iterator get_key(ssset& s, std::string key) 
{ 
    ssset::iterator it = s.lower_bound(std::make_pair(key, "")); 
    if (it != s.end() && it->first == key) return it; 
    return s.end(); 
} 

for (ssset::iterator it = get_key(s, "abc"); it != s.end() && it->first == "abc"; ++it) 
    std::cout << it->first << "->" << it->second << std::endl; 
+0

Vấn đề là bây giờ tôi không thể yêu cầu (các) giá trị được liên kết với một khóa, vì một cặp được yêu cầu cho tìm kiếm. – Qwertie

+0

Bạn có thể tìm kiếm giới hạn dưới của (khóa, ""). Nếu tìm thấy với khóa đó là giá trị đầu tiên. Lặp lại cho đến khi phím khác bắt đầu. Điều này có thể kèm theo trong adapter tôi đã đề cập – PiotrNycz

5

std::map<std::string, std::set<std::string>> sẽ xuất hiện để có exactamondo các thuộc tính bạn đang tìm kiếm (mặc dù phức tạp thua kém unordered_mapunordered_set).

+0

Ông đang sử dụng một multimap bởi vì ông có nhiều phím. – Rapptz

+0

Nhưng ("a", ("a")) được phép trong công trình của bạn ... – PiotrNycz

+0

bản đồ và multimap cũng cho phép "a", "a". Lời đề nghị của DeadMG là hoàn toàn khả thi nhưng không lý tưởng cho tình huống của tôi (xem bình luận ở trên ... đặc biệt là vì tôi đang ở trên C++ 03 => lo lắng nhiều hơn về các nhà xây dựng sao chép.) – Qwertie

Các vấn đề liên quan