mencari dalam vektor sangat lambat karena Anda harus melihat setiap elemen dari vektor jadi pertimbangkan untuk menggunakan peta jika Anda melakukan banyak pencarian
naumcho
7
@naumcho: Jika vektor diurutkan selalu ada pencarian biner, seperti yang diposting di bawah ini. Ini membuatnya secepat peta dan jika Anda hanya menyimpan nilai (bukan peta kunci / nilai) maka itu akan menggunakan memori yang jauh lebih sedikit.
Adam Hawes
4
peta tentu bukan pilihan terbaik, tetapi menggunakan set mungkin berguna. Jika Anda membutuhkan O (1) waktu pencarian, hash_set adalah cara untuk pergi.
#include<vector>vector<int> vec;//can have other data types instead of int but must same datatype as item
std::find(vec.begin(), vec.end(), item)!= vec.end()
Ini mengembalikan bool ( truejika ada, falsejika tidak). Dengan contoh Anda:
Saya tidak melihat bagaimana count () bisa lebih cepat daripada find (), karena find () berhenti segera setelah satu elemen ditemukan, sementara count () selalu harus memindai seluruh urutan.
Éric Malenfant
114
Jangan lupa #include <algorithm>atau Anda mungkin mendapatkan kesalahan yang sangat aneh seperti 'tidak dapat menemukan fungsi yang cocok di namespace std'
rustyx
80
Apakah itu tidak mengganggu siapa pun yang meskipun STL "berorientasi objek", .find()masih bukan fungsi anggota std::vector, seperti yang Anda harapkan seharusnya? Saya ingin tahu apakah ini merupakan konsekuensi dari templating.
bobobobo
71
@bobobobo: OOP tidak ada hubungannya dengan anggota vs. bukan anggota. Dan ada mazhab pemikiran luas bahwa jika sesuatu tidak harus menjadi anggota, atau ketika itu tidak memberikan keuntungan apa pun ketika diterapkan sebagai anggota, maka itu tidak boleh menjadi anggota; std::vector<>::find()tidak akan memberikan keuntungan, juga tidak diperlukan, oleh karena itu, tidak, tidak boleh menjadi anggota Lihat juga en.wikipedia.org/wiki/Coupling_%28computer_programming%29
Sebastian Mach
36
@ respir Saya berpendapat bahwa "ketika tidak memberikan keuntungan apa pun ketika diterapkan sebagai anggota" adalah salah untuk kasus ini. Keuntungannya adalah antarmuka yang disederhanakan dan lebih jelas. Misalnya: mvec.find(key) != mvec.cend()lebih disukai daripada std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend().
swalog
113
Seperti yang orang lain katakan, gunakan STL findatau find_iffungsinya. Tetapi jika Anda sedang mencari dalam vektor yang sangat besar dan kinerja dampak ini, Anda mungkin ingin mengurutkan vektor Anda dan kemudian menggunakan binary_search, lower_boundatau upper_boundalgoritma.
Jawaban yang bagus! Temukan selalu o (n). lower_bound adalah o (log (n)) jika digunakan dengan iterator akses acak.
Stephen Edmonds
30
Penyortiran adalah O (nlogn), jadi itu hanya bernilai jika Anda melakukan lebih dari pencarian O (logn).
liori
7
@liori Benar itu tergantung pada pola penggunaan Anda. Jika Anda hanya perlu mengurutkannya sekali, maka berulang kali lakukan banyak pencarian yang bisa menyelamatkan Anda.
Brian Neal
1
@Brian Neal, mengurutkan vektor besar bernilai jika harus ada banyak pencarian elemen di atasnya. Penyortiran akan menjadi O (nlogn) dan O (n) akan lebih baik jika seseorang harus menemukan elemen hanya sekali :)
Swapnil B.
47
Gunakan find dari header algoritma stl. Saya telah menggambarkan penggunaannya dengan tipe int. Anda dapat menggunakan jenis apa pun yang Anda suka selama Anda dapat membandingkan untuk kesetaraan (kelebihan == jika Anda perlu untuk kelas kustom Anda).
#include<algorithm>#include<vector>usingnamespace std;int main(){typedefvector<int>IntContainer;typedefIntContainer::iteratorIntIterator;IntContainer vw;//...// find 5IntIterator i = find(vw.begin(), vw.end(),5);if(i != vw.end()){// found it}else{// doesn't exist}return0;}
Bergantung pada kebutuhan OP, find_if () juga bisa sesuai. Hal ini memungkinkan untuk mencari menggunakan predikat sewenang-wenang alih-alih kesetaraan.
Éric Malenfant
Ups, lihat komentar Anda terlambat. Jawaban yang saya berikan juga menyebutkan find_if.
Frank
39
Jika vektor Anda tidak dipesan, gunakan pendekatan yang disarankan MSN:
if(std::find(vector.begin(),vector.end(), item)!=vector.end()){// Found the item}
Jika vektor Anda dipesan, gunakan metode binary_search Brian Neal yang disarankan:
if(binary_search(vector.begin(),vector.end(), item)){// Found the item}
pencarian biner menghasilkan O (log n) kinerja kasus terburuk, yang jauh lebih efisien daripada pendekatan pertama. Untuk menggunakan pencarian biner, Anda dapat menggunakan qsort untuk mengurutkan vektor terlebih dahulu untuk memastikan itu dipesan.
Pencarian biner akan berkinerja lebih baik untuk wadah yang lebih besar, tetapi untuk wadah kecil, pencarian linier sederhana cenderung lebih cepat, atau lebih cepat.
dan Anda dapat membuatnya berfungsi untuk daftar atau vektor dengan menggunakan 2 nama ketik
Erik Aronesty
@ErikAronesty Anda bisa lolos dengan 1 argumen templat jika Anda gunakan value_typedari wadah untuk jenis elemen. Saya telah menambahkan jawaban seperti ini.
Martin Broadhurst
13
Di C ++ 11 Anda dapat menggunakan any_of. Sebagai contoh jika itu adalah vector<string> v;maka:
Perhatikan bahwa Anda dapat lolos dengan 1 parameter templat karena Anda dapat mengekstraknya value_typedari Container. Anda memerlukan typenamekarena itu Container::value_typeadalah nama dependen .
Perhatikan bahwa ini kadang-kadang agak terlalu luas - ini akan berfungsi untuk std :: set misalnya, tetapi memberikan kinerja yang buruk dibandingkan dengan fungsi anggota find (). Saya telah menemukan yang terbaik untuk menambahkan spesialisasi untuk wadah dengan pencarian yang lebih cepat (set / peta, unordered_ *)
Andy Krouwel
10
Ingatlah bahwa, jika Anda akan melakukan banyak pencarian, ada wadah STL yang lebih baik untuk itu. Saya tidak tahu apa aplikasi Anda, tetapi wadah asosiatif seperti std :: map mungkin perlu dipertimbangkan.
std :: vector adalah wadah pilihan kecuali Anda memiliki alasan untuk yang lain, dan pencarian berdasarkan nilai dapat menjadi alasan seperti itu.
Bahkan dengan pencarian berdasarkan nilai vektor bisa menjadi pilihan yang baik, asalkan diurutkan dan Anda menggunakan binary_search, lower_bound atau upper_bound. Jika isi wadah berubah di antara pencarian, vektor tidak terlalu bagus karena kebutuhan untuk menyortir lagi.
Ingatlah bahwa ada juga fungsi find_if , yang dapat Anda gunakan jika pencarian Anda lebih kompleks, yaitu jika Anda tidak hanya mencari elemen, tetapi, misalnya, ingin melihat apakah ada elemen yang memenuhi elemen tertentu kondisi, misalnya, string yang dimulai dengan "abc". ( find_ifakan memberi Anda iterator yang menunjuk ke elemen tersebut pertama).
#include<algorithm>#include<vector>// You can use class, struct or primitive data type for ItemstructItem{//Some fields};typedef std::vector<Item>ItemVector;typedefItemVector::iteratorItemIterator;//...ItemVector vtItem;//... (init data for vtItem)Item itemToFind;//...ItemIterator itemItr;
itemItr = std::find(vtItem.begin(), vtItem.end(), itemToFind);if(itemItr != vtItem.end()){// Item found// doThis()}else{// Item not found// doThat()}
Anda dapat menggunakan findfungsi, yang ditemukan di stdnamespace, yaitu std::find. Anda melewatkan std::findfungsi begindan enditerator dari vektor yang ingin Anda cari, bersama dengan elemen yang Anda cari dan membandingkan iterator yang dihasilkan dengan ujung vektor untuk melihat apakah mereka cocok atau tidak.
#include<algorithm>#include<iostream>#include<vector>template<typenameContainer>bool search_vector(constContainer& vec,constContainer& searchvec){return std::search(vec.begin(), vec.end(), searchvec.begin(), searchvec.end())!= vec.end();}int main(){
std::vector<int> v ={2,4,6,8};//THIS WORKS. SEARCHING ONLY ONE ELEMENT.
std::vector<int> searchVector1 ={2};if(search_vector(v,searchVector1))
std::cout<<"searchVector1 found"<<std::endl;else
std::cout<<"searchVector1 not found"<<std::endl;//THIS WORKS, AS THE ELEMENTS ARE SEQUENTIAL.
std::vector<int> searchVector2 ={6,8};if(search_vector(v,searchVector2))
std::cout<<"searchVector2 found"<<std::endl;else
std::cout<<"searchVector2 not found"<<std::endl;//THIS WILL NOT WORK, AS THE ELEMENTS ARE NOT SEQUENTIAL.
std::vector<int> searchVector3 ={8,6};if(search_vector(v,searchVector3))
std::cout<<"searchVector3 found"<<std::endl;else
std::cout<<"searchVector3 not found"<<std::endl;}
Juga ada fleksibilitas melewati beberapa algoritma pencarian. Rujuk ke sini.
Saya pribadi telah menggunakan template akhir-akhir ini untuk menangani beberapa jenis wadah sekaligus daripada hanya berurusan dengan vektor. Saya menemukan contoh serupa secara online (tidak ingat di mana) jadi kredit diberikan kepada siapa pun saya telah mencicilnya. Pola khusus ini tampaknya menangani array mentah juga.
template<typenameContainer,typename T =typename std::decay<decltype(*std::begin(std::declval<Container>()))>::type>bool contains(Container&& c, T v){return std::find(std::begin(c), std::end(c), v)!= std::end(c);}
Jawaban:
Anda dapat menggunakan
std::find
dari<algorithm>
:Ini mengembalikan bool (
true
jika ada,false
jika tidak). Dengan contoh Anda:sumber
#include <algorithm>
atau Anda mungkin mendapatkan kesalahan yang sangat aneh seperti 'tidak dapat menemukan fungsi yang cocok di namespace std'.find()
masih bukan fungsi anggotastd::vector
, seperti yang Anda harapkan seharusnya? Saya ingin tahu apakah ini merupakan konsekuensi dari templating.std::vector<>::find()
tidak akan memberikan keuntungan, juga tidak diperlukan, oleh karena itu, tidak, tidak boleh menjadi anggota Lihat juga en.wikipedia.org/wiki/Coupling_%28computer_programming%29mvec.find(key) != mvec.cend()
lebih disukai daripadastd::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
.Seperti yang orang lain katakan, gunakan STL
find
ataufind_if
fungsinya. Tetapi jika Anda sedang mencari dalam vektor yang sangat besar dan kinerja dampak ini, Anda mungkin ingin mengurutkan vektor Anda dan kemudian menggunakanbinary_search
,lower_bound
atauupper_bound
algoritma.sumber
Gunakan find dari header algoritma stl. Saya telah menggambarkan penggunaannya dengan tipe int. Anda dapat menggunakan jenis apa pun yang Anda suka selama Anda dapat membandingkan untuk kesetaraan (kelebihan == jika Anda perlu untuk kelas kustom Anda).
sumber
Jika vektor Anda tidak dipesan, gunakan pendekatan yang disarankan MSN:
Jika vektor Anda dipesan, gunakan metode binary_search Brian Neal yang disarankan:
pencarian biner menghasilkan O (log n) kinerja kasus terburuk, yang jauh lebih efisien daripada pendekatan pertama. Untuk menggunakan pencarian biner, Anda dapat menggunakan qsort untuk mengurutkan vektor terlebih dahulu untuk memastikan itu dipesan.
sumber
std::sort
?qsort
sangat tidak efisien pada vektor .... lihat: stackoverflow.com/questions/12308243/…Saya menggunakan sesuatu seperti ini ...
... seperti itu sebenarnya jelas dan dapat dibaca. (Jelas Anda dapat menggunakan kembali templat di banyak tempat).
sumber
value_type
dari wadah untuk jenis elemen. Saya telah menambahkan jawaban seperti ini.Di C ++ 11 Anda dapat menggunakan
any_of
. Sebagai contoh jika itu adalahvector<string> v;
maka:Atau, gunakan lambda:
sumber
bind1st
danbind2nd
sudah usang sejak C ++ 11 dan sepenuhnya dihapus di C ++ 17. Gunakanbind
denganplaceholders
dan / atau lambda sebagai gantinya.Inilah fungsi yang akan bekerja untuk semua Kontainer:
Perhatikan bahwa Anda dapat lolos dengan 1 parameter templat karena Anda dapat mengekstraknya
value_type
dari Container. Anda memerlukantypename
karena ituContainer::value_type
adalah nama dependen .sumber
Ingatlah bahwa, jika Anda akan melakukan banyak pencarian, ada wadah STL yang lebih baik untuk itu. Saya tidak tahu apa aplikasi Anda, tetapi wadah asosiatif seperti std :: map mungkin perlu dipertimbangkan.
std :: vector adalah wadah pilihan kecuali Anda memiliki alasan untuk yang lain, dan pencarian berdasarkan nilai dapat menjadi alasan seperti itu.
sumber
Gunakan fungsi temukan STL .
Ingatlah bahwa ada juga fungsi find_if , yang dapat Anda gunakan jika pencarian Anda lebih kompleks, yaitu jika Anda tidak hanya mencari elemen, tetapi, misalnya, ingin melihat apakah ada elemen yang memenuhi elemen tertentu kondisi, misalnya, string yang dimulai dengan "abc". (
find_if
akan memberi Anda iterator yang menunjuk ke elemen tersebut pertama).sumber
Dengan peningkatan, Anda dapat menggunakan
any_of_equal
:sumber
Anda dapat mencoba kode ini:
sumber
Anda dapat menggunakan
find
fungsi, yang ditemukan distd
namespace, yaitustd::find
. Anda melewatkanstd::find
fungsibegin
danend
iterator dari vektor yang ingin Anda cari, bersama dengan elemen yang Anda cari dan membandingkan iterator yang dihasilkan dengan ujung vektor untuk melihat apakah mereka cocok atau tidak.Anda juga dapat melakukan dereferensi iterator dan menggunakannya seperti biasa, seperti iterator lainnya.
sumber
Anda dapat menggunakan hitungan juga. Ini akan mengembalikan jumlah item yang ada dalam vektor.
sumber
find
lebih cepat daripadacount
, karena tidak terus menghitung setelah pertandingan pertama.Jika Anda ingin menemukan string dalam vektor:
sumber
Sampel lain menggunakan operator C ++.
sumber
sumber
(C ++ 17 ke atas):
bisa digunakan
std::search
jugaIni juga berguna untuk mencari urutan elemen.
Juga ada fleksibilitas melewati beberapa algoritma pencarian. Rujuk ke sini.
https://en.cppreference.com/w/cpp/algorithm/search
sumber
Saya pribadi telah menggunakan template akhir-akhir ini untuk menangani beberapa jenis wadah sekaligus daripada hanya berurusan dengan vektor. Saya menemukan contoh serupa secara online (tidak ingat di mana) jadi kredit diberikan kepada siapa pun saya telah mencicilnya. Pola khusus ini tampaknya menangani array mentah juga.
sumber
Menggunakan Newton C ++ lebih mudah, didokumentasikan sendiri dan lebih cepat daripada dengan std :: find karena mengembalikan bool secara langsung.
Saya pikir sudah jelas apa fungsinya.
sumber