Bagaimana cara memeriksa apakah std :: map berisi kunci tanpa melakukan penyisipan?

148

Satu-satunya cara yang saya temukan untuk memeriksa duplikat adalah dengan memasukkan dan memeriksa std::pair.seconduntuk false, tetapi masalahnya adalah ini masih menyisipkan sesuatu jika kunci tidak digunakan, sedangkan yang saya inginkan adalah map.contains(key);fungsi.

jmasterx
sumber

Jawaban:

305

Gunakan my_map.count( key ); hanya dapat mengembalikan 0 atau 1, yang pada dasarnya adalah hasil Boolean yang Anda inginkan.

Bergantian my_map.find( key ) != my_map.end()juga bekerja.

Potatoswatter
sumber
40
@ John: Itu berbau optimasi prematur. Pada GCC (dan saya yakin sistem yang paling masuk akal), map::countdiimplementasikan sebagai find(__x) == end() ? 0 : 1;. Untuk multimapAnda mungkin memiliki argumen kinerja, tapi itu bukan pertanyaan OP dan saya masih lebih suka keanggunan.
Potatoswatter
42
Tidak, argumen pengoptimalan prematur hanya valid jika pengoptimalan memerlukan upaya yang dalam hal ini tidak.
markh44
13
Tidak benar. Ini tidak prematur jika membuat kode lebih mudah dibaca atau menghilangkan overhead yang tidak perlu. Dalam hal ini, jika count () diimplementasikan via find (), maka memanggil find () secara langsung menghilangkan pemanggilan fungsi ... ergo, ini adalah optimasi yang matang . Saya menemukan bahwa menggunakan panggilan find () lebih jelas, juga, tapi itu murni preferensi pribadi.
Tim Keating
9
Ini bukan optimasi prematur untuk menyadari perf fungsi perpustakaan sebelum Anda terbiasa menggunakannya. Dalam hal ini, Anda benar, itu tidak masalah, tetapi tidak juga perbedaan gaya sangat kecil antara menemukan dan menghitung. Saya pikir Anda mengambil retorika 'optimasi prematur' terlalu jauh. Anda harus mengambil kebiasaan optimasi "gratis" yang dapat Anda temukan dan menggunakannya untuk pengembangan sehari-hari. Ketika coders menyerah pada perangkap membayar biaya dalam keterbacaan / waktu dev / etc, semua untuk "keuntungan kinerja" yang tidak terukur bahwa retorika optimasi prematur menjadi saran yang tepat untuk diberikan.
VoidStar
10
Jauh di luar, std seharusnya hanya menambahkan has(k)/ contains(k)seperti setiap kelas peta waras lainnya di planet ini. Desain antarmuka buruk. Pendekatan find () terlalu bertele-tele dan count(k)pendekatannya jelas tidak setara dengan semantik has(k). Dalam hal ini tidak ada find(k). Lihat jumlah tampilan pada pertanyaan ini.
Jarrod Smith
46

Jawaban Potatoswatter baik-baik saja, tetapi saya lebih suka menggunakan findatau lower_boundsebagai gantinya. lower_boundini sangat berguna karena iterator yang dikembalikan selanjutnya dapat digunakan untuk penyisipan yang diisyaratkan, jika Anda ingin memasukkan sesuatu dengan kunci yang sama.

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
}
Chris Jester-Young
sumber
Ini agak berbeda dari bagaimana dia mengatakan dia melakukannya ... satu-satunya perbedaan adalah bahwa perhitungan valuedapat dilewati jika penyisipan tidak perlu.
Potatoswatter
1
Tentu, saya mengerti bahwa OP tidak peduli untuk memasukkan, jadi lower_boundsolusi berbasiskan adalah berlebihan. Saya agak hanya menyebutkan jawaban saya "untuk kelengkapan"; seperti yang saya katakan, milik Anda sangat memadai. :-)
Chris Jester-Young
4
Yap, ini jawaban yang bagus dan saya tidak setuju dengan apa pun. Hanya menunjukkan hubungan dengan alternatif insertapriori. Sebenarnya, ada perbedaan lain jika menggunakan a multimap, lower_boundmetode menyisipkan di awal rentang yang setara sedangkan insertmetode polos menambah akhir rentang.
Potatoswatter
2
Bukan jawaban untuk pertanyaan itu, tetapi pertanyaan saya yang buruk bertanya menuntun saya ke jawaban yang benar di sini ... Saya perlu melakukan insert / update. : D
Hunter-Orionnoir
1
@ Pemburu Bisakah Anda menunjukkan kode Anda kepada saya? Jika tidak masif, saya mungkin bisa memeriksanya untuk Anda.
Chris Jester-Young
8

Desideratum Anda,, map.contains(key)dijadwalkan untuk konsep standar C ++ 2a . Pada 2017 diterapkan oleh gcc 9.2 . Itu juga dalam dentang saat ini .

Camille Goudeseune
sumber
Ini adalah fitur yang bagus! Saya pikir itu telah mendarat di C ++ 20. cppreference.com
Franklin Yu