Все, что я хочу сделать, это проверить, существует ли элемент в векторе или нет, поэтому я могу иметь дело с каждым случаем.Как узнать, присутствует ли элемент в std :: vector?
if (item_present)
do_this();
else
do_that();
Все, что я хочу сделать, это проверить, существует ли элемент в векторе или нет, поэтому я могу иметь дело с каждым случаем.Как узнать, присутствует ли элемент в std :: vector?
if (item_present)
do_this();
else
do_that();
Вы можете использовать std::find
из <algorithm>
:
std::find(vector.begin(), vector.end(), item) != vector.end()
Это возвращает логическое значение (true
, если присутствует, в противном случае false
). В вашем примере:
#include <algorithm>
if (std::find(vector.begin(), vector.end(), item) != vector.end())
do_this();
else
do_that();
Используя std :: count вместо (std :: count (...)> 0), было бы «быстрее в теории»? – Klaim
Возможно. Это зависит от того, как часто вы ищете пустые векторы. – MSN
Я не вижу, как count() может быть быстрее, чем find(), так как find() останавливается, как только один элемент найден, а count() всегда должен сканировать всю последовательность. –
Использовать поиск из заголовка алгоритма stl.Я проиллюстрировал его использование с использованием типа int. Вы можете использовать любой тип, который вам нравится, пока вы можете сравнить для равенства (перегрузка ==, если вам нужно для своего пользовательского класса).
В зависимости от потребностей OP, find_if() также может быть уместным. Он позволяет искать с использованием произвольного предиката вместо равенства. –
К сожалению, ваш комментарий слишком поздно. Ответ, который я дал, также упоминает find_if. – Frank
Используйте функцию STL find.
Помните, что существует также функция find_if, которую вы можете использовать, если ваш поиск сложнее, т.е. если вы ищете не только элемент, но, например, хотите увидеть, есть ли элемент который выполняет определенное условие, например, строку, начинающуюся с «abc». (find_if
даст вам итератор, который указывает на первый такой элемент).
Как уже говорилось, используйте функции STL find
или find_if
. Но если вы ищете очень большие векторы, и это влияет на производительность, вы можете отсортировать свой вектор, а затем использовать алгоритмы, lower_bound
или upper_bound
.
Найти всегда o (n). lower_bound is o (log (n)), если используется с итераторами с произвольным доступом. –
Сортировка O (nlogn), хотя, только если вы выполняете поиск более O (logn). – liori
@liori Правда, это зависит от ваших шаблонов использования. Если вам нужно только отсортировать его один раз, затем многократно выполняет много поисков, которые он может сэкономить. –
Имейте в виду, что если вы собираетесь делать много поисков, есть контейнеры STL, которые лучше для этого. Я не знаю, что ваше приложение, но ассоциативные контейнеры, такие как std :: map, заслуживают рассмотрения.
std :: vector - это контейнер выбора, если у вас нет причины для другого, и поиск по значению может быть такой причиной.
Даже при поиске по значению вектор может быть хорошим выбором, если он отсортирован, и вы используете binary_search, lower_bound или upper_bound.Если содержимое контейнера изменяется между поиском, вектор не очень хорош из-за необходимости снова сортировать. –
Вы можете попробовать этот код:
#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()
}
Если вектор не упорядочен, использовать подход 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' очень неэффективен для векторов .... см .: http://stackoverflow.com/questions/12308243/trying-to-use-qsort-with-vector –
Двоичный поиск будет работать лучше для больших контейнеров, но для небольшие контейнеры, простой линейный поиск, вероятно, будет таким же быстрым или быстрым. – BillT
Если вы хотите найти строку в векторе:
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));
я использую что-то вроде этого ...
#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
... как то, как это на самом деле ясно и читаемым. (Очевидно, вы можете повторно использовать шаблон в нескольких местах).
, и вы можете заставить его работать для списков или векторов, используя 2 typenames –
@ErikAronesty вы можете уйти с 1 аргументом шаблона, если вы используете 'value_type' из контейнера для типа элемента. Я добавил такой ответ. –
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;
}
Вы можете использовать функцию 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++ 11 вы можете использовать any_of
. Например, если это vector<string> v;
то:
if (any_of(v.begin(), v.end(), bind2nd(equal_to<string>(), item)))
do_this();
else
do_that();
Вот функция, которая будет работать на любой контейнер:
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
- это dependent name.
Обратите внимание, что это иногда немного шире - например, оно будет работать для std :: set, но при этом дает ужасную производительность по сравнению с функцией-членом find(). Я нашел, что лучше всего добавить специализацию для контейнеров с более быстрым поиском (set/map, unordered_ *) –
Другой пример использования операторов 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!");
}
}
Я бы не рекомендовал злоупотреблять перегрузкой оператора таким образом. – Leon
Леон, я согласен с тобой, семантически это неправильно. Я использую его, чтобы сделать модульные тесты более четкими. –
С повышением вы можете использовать any_of_equal
:
#include <boost/algorithm/cxx11/any_of.hpp>
bool item_present = boost::algorithm::any_of_equal(vector, element);
поиск в векторе очень медленно, так как вы должны смотреть на каждый элемент вектора так, рассмотреть возможность использования карты, если вы делаете много поисков – naumcho
@naumcho: Если вектор отсортирован, всегда есть двоичный поиск, как показано ниже. Это делает его так же быстро, как карта, и если вы только сохраняете значения (не карты ключей/значений), тогда он будет использовать намного меньше памяти. Карты –
, конечно, не самый лучший выбор, но использование набора может оказаться полезным. Если вам нужно O (1) время поиска, hash_set - это путь. – Philipp