Все, что я хочу сделать, это проверить, существует ли элемент в векторе или нет, чтобы я мог разобраться с каждым случаем.
if ( item_present )
do_this();
else
do_that();
Все, что я хочу сделать, это проверить, существует ли элемент в векторе или нет, чтобы я мог разобраться с каждым случаем.
if ( item_present )
do_this();
else
do_that();
Вы можете использовать std::find
из <algorithm>
:
#include <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».
- person rustyx; 02.03.2012
bool
. Это падение замены (или инициализации) item_present
в исходном вопросе.
- person MSN; 19.10.2012
.find()
по-прежнему не функция-член std::vector
, как вы ожидали? Интересно, не является ли это каким-то следствием использования шаблонов?
- person bobobobo; 07.12.2012
std::vector<>::find()
не даст никаких преимуществ, и в этом нет необходимости, поэтому нет, он не должен быть членом. См. Также en.wikipedia.org/wiki/Coupling_%28computer_programming%29
- person Sebastian Mach; 04.02.2013
vector.end()
один раз, прежде чем осознал, что, во-первых, если меня действительно волнует скорость, мне вообще не следует использовать find()
в векторе, а во-вторых, этот вызов vector.end()
один раз вместо двух - вряд ли вообще какое-либо улучшение.
- person ArtOfWarfare; 11.02.2013
vector
часто будет намного быстрее искать, чем map
или set
.
- person Steve Lorimer; 05.04.2013
end() call is inlined by the compiler so there's no actual
call` - это всего лишь необработанный указатель.
- person Frerich Raabe; 10.12.2013
find
не следует добавлять в качестве члена в std::vector
; Вопрос о том, имеют ли существующие члены смысл или нет, не обсуждался, и действительно, STL не очень хорошо спроектирован во многих аспектах, в основном из-за отсутствия опыта (и мой пост был ответом на bobobobo, который подразумевал, что участники являются частью концепции ООП, но их нет)
- person Sebastian Mach; 11.09.2014
mvec.find(key) != mvec.cend()
предпочтительнее std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
.
- person swalog; 29.04.2015
#include
заголовок <algorithm>
при использовании std::find
, стало еще хуже: error: cannot bind non-const lvalue reference of type ‘__gnu_cxx::__normal_iterator<const int*, std::vector<int> >&’ to an rvalue of type ‘__gnu_cxx::__normal_iterator<const int*, std::vector<int> >’
- person Kai Petzke; 12.02.2019
mvec.find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
, что не является особенно чистым интерфейсом, чем функция, не являющаяся членом.
- person James Mart; 29.06.2020
std::vector::find()
не реализовано, так как не лучше std::find()
. Проблема в том, что программист, который обновляет определенную структуру данных с std::vector
до std::multiset
(или std::set
), затем должен пройти через код и обновить каждое место, где выполняется find()
. Было бы неплохо, если бы API std::(multi)set
и std::vector
были как можно более похожими.
- person Kai Petzke; 07.12.2020
std::vector<std::shared_ptr...>
и других выражений pimpl. Кто-нибудь знает как заставить работать ??
- person Richard McFriend Oluwamuyiwa; 10.04.2021
vector
) должны имитировать концепцию контейнеров в реальном мире. Тот факт, что я должен сказать, какой тип объектов может содержать контейнер (параметр шаблона), не соответствует реальному миру, где контейнеры могут содержать все, что угодно, при условии, что там достаточно места. А поскольку поиск вещей в контейнерах - обычное дело, это должно быть частью интерфейса контейнера.
- person bitjeep; 18.06.2021
Как уже говорили другие, используйте STL find
или _ 2_ функции. Но если вы ищете в очень больших векторах и это влияет на производительность, вы можете отсортировать вектор, а затем использовать _ 3_, lower_bound
или _ 5_ алгоритмов.
Используйте 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/
- person Jason R. Mick; 16.08.2013
Я использую что-то вроде этого ...
#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
из контейнера для типа элемента. Я добавил такой ответ.
- person Martin Broadhurst; 12.02.2016
if true return true else return false
. Метод может быть следующим: return std::find(Vec.begin(), Vec.end(), Element) != Vec.end();
- person Charles Gueunet; 08.10.2020
В 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 и полностью удалены в С ++ 17. Вместо этого используйте bind
с placeholders
и / или лямбдами.
- person andreee; 30.04.2019
Вот функция, которая будет работать для любого контейнера:
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();
}
Обратите внимание, что вы можете обойтись одним параметром шаблона, потому что вы можете извлечь value_type
из контейнера. Вам нужен typename
, потому что Container::value_type
- это зависимое имя.
ranges
, так что его можно было бы просто назвать Range
, а не Container
, а Боб - ваш дядя.
- person underscore_d; 01.07.2020
Имейте в виду, что если вы собираетесь выполнять много поисков, существуют контейнеры STL, которые лучше подходят для этого. Я не знаю, что это за приложение, но, возможно, стоит подумать об ассоциативных контейнерах, таких как std :: map.
std :: vector - это предпочтительный контейнер, если у вас нет другой причины, и такой причиной может быть поиск по значению.
Используйте функцию STL find.
Имейте в виду, что существует также функция 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
, потому что он не считает после первого совпадения.
- person Camille Goudeseune; 16.08.2015
Если вы хотите найти строку в векторе:
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 ++ 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;
}
Также есть возможность прохождения некоторых поисковых алгоритмов. Обратитесь сюда.
https://en.cppreference.com/w/cpp/algorithm/search
В последнее время я лично использовал шаблоны для работы с несколькими типами контейнеров одновременно, а не только с векторами. Я нашел аналогичный пример в Интернете (не помню, где), так что заслуга принадлежит тому, у кого я это украл. Этот конкретный шаблон, похоже, также обрабатывает необработанные массивы.
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);
}
nullptr
, который вы не обрабатываете? В этом просто нет необходимости. Кроме того, вы копируете T what
, что может оказаться дорогостоящим и ненужным. Оба аргумента должны быть const
ссылками, а не текущими. Наконец, я не знаю, зачем люди пишут if (condition) return true; else return false;
, когда они могут просто писать return condition;
.
- person underscore_d; 01.07.2020
.
вместо ->
.
- person underscore_d; 03.07.2020