จะอัพเดต std :: map ได้อย่างไรหลังจากใช้วิธีค้นหา


92

จะอัพเดตค่าของคีย์ในstd::mapหลังจากใช้findวิธีนี้ได้อย่างไร?

ฉันมีแผนที่และการประกาศตัววนซ้ำดังนี้:

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

ฉันใช้แผนที่เพื่อจัดเก็บจำนวนครั้งที่เกิดขึ้นของตัวละคร

ฉันใช้ Visual C ++ 2010

คำตอบ:


133

std::map::findส่งคืนตัววนซ้ำไปยังองค์ประกอบที่พบ (หรือกลับไปที่end()หากไม่พบองค์ประกอบ) ตราบใดที่mapไม่ใช่ const คุณสามารถแก้ไของค์ประกอบที่ตัววนซ้ำชี้ไป:

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
ขอบคุณ. เป็นไปได้ไหมที่จะใช้ [] ตัวดำเนินการ
jaykumarark

1
@ เจย์: ใช่ แต่พฤติกรรมต่างกัน ดูเอกสารสำหรับฟังก์ชั่นต่าง ๆ ที่ได้รับจาก mapmap
James McNellis

3
ฉันได้รับerror: assignment of member 'std::pair<char* const, char*>::second' in read-only object:(
Tom Brito

1
@jaykumarark ฉันคิดว่าใช่ แต่ข้อเสียของการแก้ปัญหานี้คือแผนที่ต้องค้นหาตำแหน่งของรายการครั้งที่สอง (ครั้งแรกเป็นวิธีการเรียกหาของคุณ) ซึ่งเป็นการดำเนินการด้วยความซับซ้อนของ log (N) เป็นการทำซ้ำการดำเนินการเดียวกันโดยไม่จำเป็น
truthseeker

52

ฉันจะใช้ตัวดำเนินการ []

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'

ดังนั้นการใช้เทคนิคนี้จึงกลายเป็นเรื่องง่ายมากที่จะอ่านอักขระทั้งหมดจากสตรีมและนับ:

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
คำตอบของคุณยอดเยี่ยมสำหรับคำถามจริง - น่าเศร้าที่ผู้ถามพลาดที่จะถาม (และยอมรับ) สิ่งนี้อย่างชัดเจน นั่นเป็นเหตุผลที่ฉันคิดว่ามันจะดีกว่าถ้ามีคำชี้แจงสั้น ๆ เกี่ยวกับข้อเท็จจริงนี้: คนที่ "อ่าน" เร็วมากอาจเชื่อว่าคุณกำลังแนะนำให้ใช้[]หลังจากใช้ไปแล้วfind(ฉันไม่คิดว่านี่เป็นความตั้งใจของคุณ)
Wolf

ฉันคิดว่า 'ค้นหา' จะดีกว่าถ้าไม่มีใครต้องการแทรกองค์ประกอบโดยปริยาย การอ้างถึง 'ค้นหา' และการตายโดย SIGSEGV สามารถเลือกได้
Gwangmu Lee

1
@GwangmuLee การยกเลิกการอ้างอิงตัวend()วนซ้ำเป็นพฤติกรรมที่ไม่ได้กำหนดมันไม่จำเป็นต้องสร้างSIGSEGV(และจากประสบการณ์ของฉันมันไม่น่าจะทำเช่นนั้น)
Martin York

5

คุณสามารถใช้std::map::atฟังก์ชันสมาชิกโดยจะส่งกลับการอ้างอิงถึงค่าที่แมปขององค์ประกอบที่ระบุด้วยคีย์ k

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

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

1

หากคุณทราบคีย์แล้วคุณสามารถอัปเดตค่าที่คีย์นั้นได้โดยตรงโดยใช้ m[key] = new_value

นี่คือตัวอย่างโค้ดที่อาจช่วยได้:

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    


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.