Все, что я хочу сделать, это проверить, существует ли элемент в векторе или нет, чтобы я мог разобраться с каждым случаем.
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()
Это возвращает bool ( 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
алгоритмы.
Используйте find из заголовка алгоритма 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();