วิธีการตรวจสอบว่า std :: map มีรหัสโดยไม่ทำการแทรก?


148

วิธีเดียวที่ฉันได้ตรวจสอบการซ้ำคือการแทรกและตรวจสอบstd::pair.secondหาfalseแต่ปัญหาคือว่านี้ยังคงแทรกบางอย่างถ้าคีย์ไม่ได้ใช้ในขณะที่สิ่งที่ฉันต้องการคือmap.contains(key);ฟังก์ชั่น


คำตอบ:


305

ใช้my_map.count( key ); มันสามารถคืนค่า 0 หรือ 1 ซึ่งเป็นผลลัพธ์บูลีนที่คุณต้องการเป็นหลัก

ผลัดmy_map.find( key ) != my_map.end()กันเกินไป


40
@John: นั่นเป็นการเพิ่มประสิทธิภาพก่อนวัยอันควร เมื่อวันที่ GCC (และฉันแน่ใจว่าระบบที่เหมาะสมที่สุด) จะดำเนินการเป็นmap::count find(__x) == end() ? 0 : 1;สำหรับmultimapคุณอาจมีข้อโต้แย้งด้านประสิทธิภาพ แต่นั่นไม่ใช่คำถามของ OP และฉันก็ยังชอบความสง่างาม
Potatoswatter

42
ไม่ได้อาร์กิวเมนต์การปรับให้เหมาะสมก่อนกำหนดมีผลใช้ได้ก็ต่อเมื่อการปรับให้เหมาะสมใช้ความพยายามซึ่งในกรณีนี้มันจะไม่ทำงาน
markh44

13
ไม่จริง. มันไม่ได้เกิดก่อนกำหนดหากมันทำให้การอ่านรหัสง่ายขึ้นหรือกำจัดค่าใช้จ่ายที่ไม่จำเป็น ในกรณีนี้ถ้า count () ถูกนำไปใช้ผ่าน find () ต่อไปการโทร find () จะกำจัดการเรียกฟังก์ชัน ... ergo โดยตรงมันเป็นการปรับให้เหมาะสมเต็มที่แล้ว ฉันพบว่าการใช้การโทร find () นั้นชัดเจนกว่าเช่นกัน แต่นั่นเป็นการตั้งค่าส่วนตัวที่แท้จริง
ทิมคีด

9
มันไม่ใช่การปรับให้เหมาะสมก่อนเวลาอันควรที่จะตระหนักถึงความสมบูรณ์ของฟังก์ชั่นห้องสมุดก่อนที่คุณจะสร้างนิสัยในการใช้มัน ในกรณีนี้คุณพูดถูกมันไม่สำคัญ แต่ไม่มีความแตกต่างโวหารระหว่างการค้นหาและการนับ ฉันคิดว่าคุณใช้ 'การเพิ่มประสิทธิภาพก่อนวัยอันควร' ไกลเกินไป คุณควรใช้นิสัยการปรับให้เหมาะสมแบบ "ฟรี" ใด ๆ ที่คุณสามารถค้นหาและใช้เพื่อการพัฒนาประจำวัน มันคือเมื่อนักเขียนยอมให้กับดักของการจ่ายค่าใช้จ่ายในการอ่าน / dev เวลา / ฯลฯ ทั้งหมดสำหรับ "ประสิทธิภาพเพิ่ม" ที่ไม่ได้วัดซึ่งการเพิ่มประสิทธิภาพการพูดโวหารก่อนวัยอันควรกลายเป็นคำแนะนำที่เหมาะสมที่จะให้
VoidStar

10
ไกลออกไปมาตรฐานควรเพิ่ม damn has(k)/ contains(k)เหมือนคลาสแผนที่มีเหตุผลอื่น ๆ ทั้งหมดในโลก การออกแบบส่วนต่อประสานที่ไม่ดี ค้นหา () วิธีการคือ verbose เกินไปและวิธีการที่แน่นอนไม่ได้อยู่ที่ความเท่าเทียมกันความหมายกับcount(k) สำหรับเรื่องที่ไม่เป็นhas(k) find(k)ลองดูจำนวนการดูคำถามนี้
Jarrod Smith

46

คำตอบของ Potatoswatter นั้นใช้ได้ แต่ฉันชอบที่จะใช้findหรือlower_boundไม่ lower_boundมีประโยชน์อย่างยิ่งเนื่องจากตัววนซ้ำที่ส่งคืนสามารถใช้สำหรับการแทรกคำใบ้ได้ในภายหลังหากคุณต้องการแทรกบางอย่างด้วยคีย์เดียวกัน

map<K, V>::iterator iter(my_map.lower_bound(key));
if (iter == my_map.end() || key < iter->first) {    // not found
    // ...
    my_map.insert(iter, make_pair(key, value));     // hinted insertion
} else {
    // ... use iter->second here
}

สิ่งนี้แตกต่างจากวิธีที่เขาบอกว่าเขาทำ ... ความแตกต่างเพียงอย่างเดียวคือการคำนวณvalueอาจถูกข้ามไปหากไม่จำเป็นต้องใส่การแทรก
Potatoswatter

1
แน่นอนฉันเข้าใจว่า OP ไม่สนใจที่จะแทรกดังนั้นlower_boundโซลูชันที่ใช้จึงเกินความจริง ฉันเพิ่งพูดถึงคำตอบของฉัน "เพื่อความสมบูรณ์"; อย่างที่ฉันบอกว่า :-)
Chris Jester-Young

4
ใช่นี่เป็นคำตอบที่ดีและฉันไม่เห็นด้วยกับสิ่งใด เพียงแค่ชี้ให้เห็นถึงความสัมพันธ์กับทางเลือกของinsertนิรนัย ที่จริงแล้วมีความแตกต่างถ้าใช้ a multimap, lower_boundวิธีการแทรกที่จุดเริ่มต้นของช่วงเทียบเท่าในขณะที่insertวิธีธรรมดาเพิ่มไปยังจุดสิ้นสุดของช่วง
Potatoswatter

2
ไม่ใช่คำตอบของคำถาม แต่คำถามที่ไม่ดีของฉันทำให้ฉันได้คำตอบที่ถูกต้องที่นี่ ... ฉันต้องทำการแทรก / อัปเดต : D
Hunter-Orionnoir

1
@Hunter คุณสามารถแสดงรหัสของคุณให้ฉันได้ไหม ถ้ามันไม่ใหญ่โตฉันอาจจะรีวิวให้คุณ
Chris Jester-Young

9

สิ่งที่ขาดของคุณmap.contains(key)จะถูกกำหนดไว้สำหรับการร่างมาตรฐานC ++ 2a ในปี 2017 มันถูกนำมาใช้โดยGCC 9.2 นอกจากนี้ยังมีในปัจจุบันเสียงดังกราว


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