สิ่งที่ฉันต้องการทำคือการตรวจสอบว่ามีองค์ประกอบอยู่ในเวกเตอร์หรือไม่ดังนั้นฉันจึงสามารถจัดการกับแต่ละกรณีได้
if ( item_present )
do_this();
else
do_that();
สิ่งที่ฉันต้องการทำคือการตรวจสอบว่ามีองค์ประกอบอยู่ในเวกเตอร์หรือไม่ดังนั้นฉันจึงสามารถจัดการกับแต่ละกรณีได้
if ( item_present )
do_this();
else
do_that();
คำตอบ:
คุณสามารถใช้std::find
จาก<algorithm>
:
#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()
สิ่งนี้จะคืนค่าบูล ( true
ถ้ามีเป็นfalse
อย่างอื่น) ด้วยตัวอย่างของคุณ:
#include <algorithm>
#include <vector>
if ( std::find(vec.begin(), vec.end(), item) != vec.end() )
do_this();
else
do_that();
#include <algorithm>
มิฉะนั้นคุณอาจได้รับข้อผิดพลาดแปลก ๆ เช่น 'ไม่สามารถหาฟังก์ชั่นการจับคู่ในเนมสเปซ std' ได้
.find()
ก็ยังไม่ได้เป็นฟังก์ชันของสมาชิกstd::vector
อย่างที่คุณคาดหวัง ฉันสงสัยว่านี่จะเป็นผลมาจากการทำให้อุณหภูมิลดลง
std::vector<>::find()
จะไม่ให้ประโยชน์ใด ๆ และไม่จำเป็นดังนั้นจึงไม่ควรเป็นสมาชิก ดูเพิ่มเติมen.wikipedia.org/wiki/Coupling_%28computer_programming%29
mvec.find(key) != mvec.cend()
std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
อย่างที่คนอื่นพูดใช้ STL find
หรือfind_if
ฟังก์ชั่น แต่ถ้าคุณกำลังค้นหาในเวกเตอร์ขนาดใหญ่มากและส่งผลกระทบต่อประสิทธิภาพการทำงานนี้คุณอาจต้องการที่จะเรียงลำดับเวกเตอร์ของคุณแล้วใช้binary_search
, lower_bound
หรือupper_bound
อัลกอริทึม
ใช้ค้นหาจากส่วนหัวอัลกอริทึมของ stl ฉันได้แสดงให้เห็นถึงการใช้งานกับชนิด int คุณสามารถใช้ประเภทใดก็ได้ที่คุณต้องการตราบใดที่คุณสามารถเปรียบเทียบความเท่าเทียมกันได้ (เกิน == ถ้าคุณต้องการสำหรับคลาสที่กำหนดเองของคุณ)
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
typedef vector<int> IntContainer;
typedef IntContainer::iterator IntIterator;
IntContainer vw;
//...
// find 5
IntIterator i = find(vw.begin(), vw.end(), 5);
if (i != vw.end()) {
// found it
} else {
// doesn't exist
}
return 0;
}
หากไม่มีการสั่งซื้อเวกเตอร์ให้ใช้วิธีที่ MSN แนะนำ:
if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
// Found the item
}
หากมีการสั่งซื้อเวกเตอร์ของคุณให้ใช้วิธี binary_search แนะนำ Brian Neal:
if(binary_search(vector.begin(), vector.end(), item)){
// Found the item
}
การค้นหาแบบไบนารีให้ผลการทำงาน O (log n) ที่แย่ที่สุดซึ่งเป็นวิธีที่มีประสิทธิภาพมากกว่าวิธีแรก ในการใช้การค้นหาแบบไบนารีคุณอาจใช้ qsort เพื่อจัดเรียงเวกเตอร์ก่อนเพื่อรับประกันว่าจะได้รับคำสั่ง
std::sort
เหรอ qsort
ไม่มีประสิทธิภาพในเวกเตอร์ .... ดู: stackoverflow.com/questions/12308243/…
ฉันใช้สิ่งนี้ ...
#include <algorithm>
template <typename T>
const bool Contains( std::vector<T>& Vec, const T& Element )
{
if (std::find(Vec.begin(), Vec.end(), Element) != Vec.end())
return true;
return false;
}
if (Contains(vector,item))
blah
else
blah
... ด้วยวิธีการที่ชัดเจนและอ่านได้จริง (เห็นได้ชัดว่าคุณสามารถใช้แม่แบบซ้ำได้หลายที่)
value_type
จากคอนเทนเนอร์สำหรับประเภทองค์ประกอบ ฉันได้เพิ่มคำตอบเช่นนี้
ใน C ++ 11 any_of
คุณสามารถใช้ ตัวอย่างเช่นถ้ามันเป็นvector<string> v;
แล้ว:
if (any_of(v.begin(), v.end(), bind(equal_to<string>(), _1, item)))
do_this();
else
do_that();
หรือใช้แลมบ์ดา:
if (any_of(v.begin(), v.end(), [&](const std::string& elem) { return elem == item; }))
do_this();
else
do_that();
bind1st
และbind2nd
จะเลิกตั้งแต่ C ++ 11และลบออกอย่างสมบูรณ์ใน C ++ 17 ใช้bind
กับplaceholders
และ / หรือ lambdas แทน
นี่คือฟังก์ชั่นที่ใช้งานได้กับคอนเทนเนอร์ใด ๆ :
template <class Container>
const bool contains(const Container& container, const typename Container::value_type& element)
{
return std::find(container.begin(), container.end(), element) != container.end();
}
โปรดทราบว่าคุณสามารถไปด้วยพารามิเตอร์เทมเพลต 1 เนื่องจากคุณสามารถแยกvalue_type
จากคอนเทนเนอร์ คุณต้องการtypename
เพราะContainer::value_type
เป็นชื่อที่ขึ้นต่อกัน
โปรดจำไว้ว่าหากคุณกำลังทำการค้นหาจำนวนมากมี STL container ที่ดีกว่า ฉันไม่ทราบว่าแอปพลิเคชันของคุณคืออะไร แต่คอนเทนเนอร์ที่เชื่อมโยงเช่น std :: map อาจมีมูลค่าการพิจารณา
std :: vector เป็นที่เก็บของตัวเลือกเว้นแต่คุณจะมีเหตุผลสำหรับสิ่งอื่นและการค้นหาตามค่าอาจเป็นเหตุผลดังกล่าว
ใช้ STL ค้นหาฟังก์ชั่น
โปรดทราบว่านอกจากนี้ยังมีฟังก์ชั่นfind_ifซึ่งคุณสามารถใช้หากการค้นหาของคุณมีความซับซ้อนมากขึ้นเช่นหากคุณไม่ได้มองหาองค์ประกอบเพียงอย่างเดียว แต่ต้องการดูว่ามีองค์ประกอบที่เติมเต็มแน่นอนหรือไม่ เงื่อนไขตัวอย่างเช่นสตริงที่ขึ้นต้นด้วย "abc" ( find_if
จะให้ตัววนซ้ำที่ชี้ไปยังองค์ประกอบดังกล่าวแรก)
ด้วยการเพิ่มคุณสามารถใช้any_of_equal
:
#include <boost/algorithm/cxx11/any_of.hpp>
bool item_present = boost::algorithm::any_of_equal(vector, element);
คุณสามารถลองรหัสนี้:
#include <algorithm>
#include <vector>
// You can use class, struct or primitive data type for Item
struct Item {
//Some fields
};
typedef std::vector<Item> ItemVector;
typedef ItemVector::iterator ItemIterator;
//...
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()
}
คุณสามารถใช้find
ฟังก์ชั่นที่พบในstd
namespace std::find
คือ คุณผ่านstd::find
ฟังก์ชั่นbegin
และตัวend
วนซ้ำจากเวกเตอร์ที่คุณต้องการค้นหาพร้อมกับองค์ประกอบที่คุณกำลังมองหาและเปรียบเทียบตัววนซ้ำผลลัพธ์ไปยังจุดสิ้นสุดของเวกเตอร์เพื่อดูว่าตรงกันหรือไม่
std::find(vector.begin(), vector.end(), item) != vector.end()
คุณยังสามารถอ่านค่าตัววนซ้ำและใช้งานได้ตามปกติเหมือนตัววนซ้ำอื่น ๆ
คุณสามารถใช้การนับได้เช่นกัน มันจะคืนจำนวนรายการที่มีอยู่ในเวกเตอร์
int t=count(vec.begin(),vec.end(),item);
find
เร็วกว่าcount
เพราะมันไม่นับต่อไปหลังจากการแข่งขันครั้งแรก
หากคุณต้องการหาสตริงในเวกเตอร์:
struct isEqual
{
isEqual(const std::string& s): m_s(s)
{}
bool operator()(OIDV* l)
{
return l->oid == m_s;
}
std::string m_s;
};
struct OIDV
{
string oid;
//else
};
VecOidv::iterator itFind=find_if(vecOidv.begin(),vecOidv.end(),isEqual(szTmp));
ตัวอย่างอื่นที่ใช้ตัวดำเนินการ C ++
#include <vector>
#include <algorithm>
#include <stdexcept>
template<typename T>
inline static bool operator ==(const std::vector<T>& v, const T& elem)
{
return (std::find(v.begin(), v.end(), elem) != v.end());
}
template<typename T>
inline static bool operator !=(const std::vector<T>& v, const T& elem)
{
return (std::find(v.begin(), v.end(), elem) == v.end());
}
enum CODEC_ID {
CODEC_ID_AAC,
CODEC_ID_AC3,
CODEC_ID_H262,
CODEC_ID_H263,
CODEC_ID_H264,
CODEC_ID_H265,
CODEC_ID_MAX
};
void main()
{
CODEC_ID codec = CODEC_ID_H264;
std::vector<CODEC_ID> codec_list;
codec_list.reserve(CODEC_ID_MAX);
codec_list.push_back(CODEC_ID_AAC);
codec_list.push_back(CODEC_ID_AC3);
codec_list.push_back(CODEC_ID_H262);
codec_list.push_back(CODEC_ID_H263);
codec_list.push_back(CODEC_ID_H264);
codec_list.push_back(CODEC_ID_H265);
if (codec_list != codec)
{
throw std::runtime_error("codec not found!");
}
if (codec_list == codec)
{
throw std::logic_error("codec has been found!");
}
}
template <typename T> bool IsInVector(T what, std::vector<T> * vec)
{
if(std::find(vec->begin(),vec->end(),what)!=vec->end())
return true;
return false;
}
(C ++ 17 ขึ้นไป):
สามารถใช้ std::search
ยัง
สิ่งนี้ยังมีประโยชน์สำหรับการค้นหาลำดับขององค์ประกอบ
#include <algorithm>
#include <iostream>
#include <vector>
template <typename Container>
bool search_vector(const Container& vec, const Container& 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;
}
นอกจากนี้ยังมีความยืดหยุ่นในการผ่านอัลกอริทึมการค้นหาบางอย่าง อ้างอิงที่นี่
ฉันใช้เท็มเพลตล่าช้าเพื่อจัดการคอนเทนเนอร์หลายชนิดในคราวเดียวแทนที่จะจัดการกับเวกเตอร์เท่านั้น ฉันพบตัวอย่างที่คล้ายกันออนไลน์ (จำไม่ได้ว่าอยู่ที่ไหน) ดังนั้นเครดิตจะไปที่ใครก็ตามที่ฉันเคยขโมยจาก รูปแบบนี้โดยเฉพาะดูเหมือนว่าจะจัดการอาร์เรย์ดิบเช่นกัน
template <typename Container, 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);
}
การใช้Newton C ++ง่ายกว่าทำเอกสารด้วยตนเองและเร็วกว่า std :: find เนื่องจากคืนค่าบูลโดยตรง
bool exists_linear( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
bool exists_binary( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
ฉันคิดว่ามันชัดเจนว่าฟังก์ชั่นทำอะไร
include <newton/algorithm/algorithm.hpp>
if ( newton::exists_linear(first, last, value) )
do_this();
else
do_that();