Все, що я хочу зробити, - це перевірити, чи існує елемент у векторі чи ні, тому я можу розібратися з кожним випадком.
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, який запропонував Брайан Ніл:
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
і / або лямбда замість цього.
Ось функція, яка буде працювати для будь-якого контейнера:
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, які краще для цього. Я не знаю, що це за ваша програма, але асоціативні контейнери типу 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
просторі імен, тобто 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
, тому що він не продовжує рахувати після першого матчу.
Ще один зразок із використанням операторів 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 безпосередньо.
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();