Làm cách nào để cập nhật std :: map sau khi sử dụng phương thức find?


90

Làm thế nào để cập nhật giá trị của một khóa std::mapsau khi sử dụng findphương thức?

Tôi có một khai báo bản đồ và trình lặp như thế này:

map <char, int> m1;
map <char, int>::iterator m1_it;
typedef pair <char, int> count_pair;

Tôi đang sử dụng bản đồ để lưu trữ số lần xuất hiện của một nhân vật.

Tôi đang sử dụng Visual C ++ 2010.

Câu trả lời:


130

std::map::findtrả về một trình lặp cho phần tử tìm thấy (hoặc end()nếu phần tử không được tìm thấy). Miễn maplà không phải là const, bạn có thể sửa đổi phần tử được trỏ tới bởi trình vòng lặp:

std::map<char, int> m;
m.insert(std::make_pair('c', 0));  // c is for cookie

std::map<char, int>::iterator it = m.find('c'); 
if (it != m.end())
    it->second = 42;

2
Cảm ơn. Cũng có thể sử dụng toán tử []?
jaykumarark

1
@Jay: Có, nhưng hành vi thì khác. Xem các maptài liệu hướng dẫn cho các chức năng khác nhau được cung cấp bởi map.
James McNellis

3
Tôi nhận được error: assignment of member 'std::pair<char* const, char*>::second' in read-only object:(
Tom Brito,

1
@jaykumarark Tôi nghĩ là có, nhưng nhược điểm của giải pháp này là, bản đồ phải tìm vị trí của mục lần thứ hai (lần đầu tiên là lệnh gọi phương thức tìm của bạn), hoạt động với độ phức tạp của log (N). Nó là sự sao chép không ngừng của cùng một hoạt động.
truthseeker

51

Tôi sẽ sử dụng toán tử [].

map <char, int> m1;

m1['G'] ++;  // If the element 'G' does not exist then it is created and 
             // initialized to zero. A reference to the internal value
             // is returned. so that the ++ operator can be applied.

// If 'G' did not exist it now exist and is 1.
// If 'G' had a value of 'n' it now has a value of 'n+1'

Vì vậy, bằng cách sử dụng kỹ thuật này, việc đọc tất cả các ký tự từ một luồng và đếm chúng trở nên thực sự dễ dàng:

map <char, int>                m1;
std::ifstream                  file("Plop");
std::istreambuf_iterator<char> end;

for(std::istreambuf_iterator<char> loop(file); loop != end; ++loop)
{
    ++m1[*loop]; // prefer prefix increment out of habbit
}

3
Câu trả lời của bạn là tuyệt vời cho câu hỏi thực tế - thật đáng buồn là người hỏi đã không hỏi (và do đó chấp nhận) điều này theo cách hiển nhiên. Đó là lý do tại sao tôi nghĩ sẽ tốt hơn nếu có một phát biểu ngắn về thực tế này: những người "đọc" rất nhanh, có thể tin rằng bạn đang đề nghị sử dụng []sau khi đã sử dụng find(tôi không nghĩ rằng đây là ý định của bạn).
Wolf

Tôi nghĩ rằng 'find' có thể tốt hơn nếu người ta không muốn chèn ngầm một phần tử. Việc hủy bỏ 'tìm kiếm' và chết bởi SIGSEGV có thể được ưu tiên hơn.
Gwangmu Lee

1
@GwangmuLee Bỏ tham chiếu tới end()trình lặp là hành vi không xác định, nó không cần tạo ra một SIGSEGV(và theo kinh nghiệm của tôi thì không có khả năng làm như vậy).
Martin York

5

Bạn có thể sử dụng std::map::athàm thành viên, nó trả về một tham chiếu đến giá trị được ánh xạ của phần tử được xác định bằng khóa k.

std::map<char,int> mymap = {
                               { 'a', 0 },
                               { 'b', 0 },
                           };

  mymap.at('a') = 10;
  mymap.at('b') = 20;

1

Nếu bạn đã biết khóa, bạn có thể cập nhật trực tiếp giá trị tại khóa đó bằng cách sử dụng m[key] = new_value

Đây là mã mẫu có thể hữu ích:

map<int, int> m;

for(int i=0; i<5; i++)
    m[i] = i;

for(auto it=m.begin(); it!=m.end(); it++)
    cout<<it->second<<" ";
//Output: 0 1 2 3 4

m[4] = 7;  //updating value at key 4 here

cout<<"\n"; //Change line

for(auto it=m.begin(); it!=m.end(); it++)
    cout<<it->second<<" ";
// Output: 0 1 2 3 7    

0

Bạn cũng có thể làm như thế này-

 std::map<char, int>::iterator it = m.find('c'); 
 if (it != m.end())
 (*it).second = 42;

0

Bạn có thể cập nhật giá trị như sau

   auto itr = m.find('ch'); 
     if (itr != m.end()){
           (*itr).second = 98;
     }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.