поиск в векторе очень медленный, так как вы должны смотреть на каждый элемент вектора, поэтому рассмотрите возможность использования карты, если вы выполняете много поисков
naumcho
7
@naumcho: если вектор отсортирован, всегда есть бинарный поиск, как показано ниже. Это делает его таким же быстрым, как карта, и если вы храните только значения (а не карты ключ / значение), тогда он будет использовать намного меньше памяти.
Адам Хос
4
Карты, конечно, не лучший выбор, но использование набора может быть полезным. Если вам нужно время поиска O (1), лучше использовать hash_set.
#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противном случае). С вашим примером:
Я не понимаю, как count () может быть быстрее, чем find (), поскольку find () останавливается, как только найден один элемент, а count () всегда должен сканировать всю последовательность.
Эрик Маленфант
114
Не забывайте об этом, #include <algorithm>иначе вы можете получить очень странные ошибки, такие как «не могу найти подходящую функцию в пространстве имен std»
rustyx
80
Разве это никого не беспокоило, что, несмотря на то, что STL является «объектно-ориентированным», .find()он все еще не является функцией-членом std::vector, как и следовало ожидать? Интересно, это как-то является следствием шаблонов?
Бобобобо
71
@bobobobo: ООП не имеет ничего общего с членами или не членами. И существует широко распространенное мнение о том, что если что-то не обязательно должно быть членом или когда оно не дает никаких преимуществ при реализации в качестве члена, то оно не должно быть членом; std::vector<>::find()не даст никакого преимущества, и при этом он не нужен, поэтому нет, он не должен быть членом. См. Также en.wikipedia.org/wiki/Coupling_%28computer_programming%29
Себастьян Мах
36
@phresnel Я бы сказал, что «когда он не дает никаких преимуществ при реализации в качестве члена», в этом случае ложь. Преимущество заключается в упрощенном и понятном интерфейсе. Например: mvec.find(key) != mvec.cend()предпочтительнее std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend().
Суалог
113
Как уже говорили другие, используйте STL findили find_ifфункции. Но если вы ищете в очень больших векторов , и это влияет на производительность, вы можете сортировать вектор , а затем использовать binary_search, lower_boundили upper_boundалгоритмы.
Хороший ответ! Найти всегда о (п). lower_bound равен o (log (n)), если используется с итераторами с произвольным доступом.
Стивен Эдмондс
30
Сортировка - это O (nlogn), поэтому она стоит только если вы выполняете больше, чем O (logn) поиск.
Лиори
7
@liori Правда, это зависит от ваших моделей использования. Если вам нужно отсортировать его только один раз, а затем многократно выполнять поиск, это может спасти вас.
Брайан Нил
1
@ Брайан Нил, сортировка большого вектора стоит того, чтобы на нем было много элементов поиска. Сортировка будет O (nlogn), а O (n) будет лучше, если нужно найти элемент только один раз :)
Swapnil B.
47
Используйте find из заголовка алгоритма stl. Я проиллюстрировал его использование с типом int. Вы можете использовать любой понравившийся вам тип, если вы можете сравнить на равенство (перегрузка ==, если вам нужно для вашего пользовательского класса).
#include<algorithm>#include<vector>usingnamespace std;int main(){typedefvector<int>IntContainer;typedefIntContainer::iteratorIntIterator;IntContainer vw;//...// find 5IntIterator i = find(vw.begin(), vw.end(),5);if(i != vw.end()){// found it}else{// doesn't exist}return0;}
В зависимости от потребностей OP, find_if () также может быть подходящим. Это позволяет искать, используя произвольный предикат вместо равенства.
Эрик Маленфант
К сожалению, ваш комментарий слишком поздно. Ответ, который я дал, также упоминает find_if.
Фрэнк
39
Если ваш вектор не упорядочен, используйте подход, предложенный 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, чтобы сначала отсортировать вектор, чтобы гарантировать его упорядоченность.
Бинарный поиск будет работать лучше для больших контейнеров, но для небольших контейнеров простой линейный поиск, вероятно, будет таким же быстрым или быстрым.
Обратите внимание, что вы можете обойтись без 1 параметра шаблона, потому что вы можете извлечь value_typeиз контейнера. Вам нужно, typenameпотому что Container::value_typeэто зависимое имя .
Обратите внимание, что это иногда слишком широко - например, это работает для std :: set, но дает ужасную производительность по сравнению с функцией-членом find (). Я нашел, что лучше всего добавить специализацию для контейнеров с более быстрым поиском (set / map, unordered_ *)
Andy Krouwel
10
Имейте в виду, что, если вы собираетесь выполнять много поисков, есть контейнеры STL, которые лучше подходят для этого. Я не знаю, какое у вас приложение, но стоит рассмотреть такие ассоциативные контейнеры, как std :: map.
std :: vector является контейнером выбора, если у вас нет причины для другого, и поиск по значению может быть такой причиной.
Даже при поиске по значению вектор может быть хорошим выбором, если он отсортирован и вы используете binary_search, lower_bound или upper_bound. Если содержимое контейнера изменяется между поисками, вектор не очень хорош из-за необходимости повторной сортировки.
Имейте в виду, что есть также функция find_if , которую вы можете использовать, если ваш поиск более сложный, т.е. если вы не просто ищете элемент, но, например, хотите посмотреть, есть ли элемент, который удовлетворяет определенному условие, например, строка, которая начинается с "abc". ( find_ifдаст вам итератор, который указывает на первый такой элемент).
#include<algorithm>#include<vector>// You can use class, struct or primitive data type for ItemstructItem{//Some fields};typedef std::vector<Item>ItemVector;typedefItemVector::iteratorItemIterator;//...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итератор из вектора вы хотите найти, наряду с элементом вы ищете и сравнить полученный итератор к концу вектора , чтобы увидеть , если они совпадают или нет.
Это также полезно для поиска последовательности элементов.
#include<algorithm>#include<iostream>#include<vector>template<typenameContainer>bool search_vector(constContainer& vec,constContainer& 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<typenameContainer,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);}
Ответы:
Вы можете использовать
std::find
от<algorithm>
:Это возвращает bool (
true
если присутствует, вfalse
противном случае). С вашим примером:источник
#include <algorithm>
иначе вы можете получить очень странные ошибки, такие как «не могу найти подходящую функцию в пространстве имен std».find()
он все еще не является функцией-членомstd::vector
, как и следовало ожидать? Интересно, это как-то является следствием шаблонов?std::vector<>::find()
не даст никакого преимущества, и при этом он не нужен, поэтому нет, он не должен быть членом. См. Также en.wikipedia.org/wiki/Coupling_%28computer_programming%29mvec.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. Вы можете использовать любой понравившийся вам тип, если вы можете сравнить на равенство (перегрузка ==, если вам нужно для вашего пользовательского класса).
источник
Если ваш вектор не упорядочен, используйте подход, предложенный MSN:
Если ваш вектор упорядочен, используйте метод binary_search, предложенный Брайаном Нилом:
Бинарный поиск дает O (log n) производительность в худшем случае, что намного эффективнее, чем первый подход. Чтобы использовать бинарный поиск, вы можете использовать qsort, чтобы сначала отсортировать вектор, чтобы гарантировать его упорядоченность.
источник
std::sort
?qsort
очень неэффективно для векторов .... см .: stackoverflow.com/questions/12308243/…Я использую что-то вроде этого ...
... так оно и есть на самом деле понятно и читаемо. (Очевидно, вы можете повторно использовать шаблон в нескольких местах).
источник
value_type
из контейнера для типа элемента. Я добавил ответ как этот.В C ++ 11 вы можете использовать
any_of
. Например, если этоvector<string> v;
тогда:В качестве альтернативы используйте лямбду:
источник
bind1st
иbind2nd
являются устаревшими , так как C ++ 11 и полностью удал ли в C ++ 17. Используйтеbind
сplaceholders
и / или лямбды вместо этого.Вот функция, которая будет работать для любого контейнера:
Обратите внимание, что вы можете обойтись без 1 параметра шаблона, потому что вы можете извлечь
value_type
из контейнера. Вам нужно,typename
потому чтоContainer::value_type
это зависимое имя .источник
Имейте в виду, что, если вы собираетесь выполнять много поисков, есть контейнеры STL, которые лучше подходят для этого. Я не знаю, какое у вас приложение, но стоит рассмотреть такие ассоциативные контейнеры, как std :: map.
std :: vector является контейнером выбора, если у вас нет причины для другого, и поиск по значению может быть такой причиной.
источник
Используйте функцию поиска STL .
Имейте в виду, что есть также функция find_if , которую вы можете использовать, если ваш поиск более сложный, т.е. если вы не просто ищете элемент, но, например, хотите посмотреть, есть ли элемент, который удовлетворяет определенному условие, например, строка, которая начинается с "abc". (
find_if
даст вам итератор, который указывает на первый такой элемент).источник
С надстройкой вы можете использовать
any_of_equal
:источник
Вы можете попробовать этот код:
источник
Вы можете использовать
find
функцию, найденную вstd
пространстве имен, то естьstd::find
. Вы передаетеstd::find
функцию,begin
иend
итератор из вектора вы хотите найти, наряду с элементом вы ищете и сравнить полученный итератор к концу вектора , чтобы увидеть , если они совпадают или нет.Вы также можете разыменовать этот итератор и использовать его как обычно, как любой другой итератор.
источник
Вы можете использовать счет тоже. Он вернет количество элементов, присутствующих в векторе.
источник
find
быстрее, чемcount
, потому что он не продолжает считать после первого матча.Если вы хотите найти строку в векторе:
источник
Еще один пример с использованием операторов C ++.
источник
источник
(C ++ 17 и выше):
можно использовать
std::search
такжеЭто также полезно для поиска последовательности элементов.
Также есть гибкость прохождения некоторых поисковых алгоритмов. Обратитесь сюда.
https://en.cppreference.com/w/cpp/algorithm/search
источник
В последнее время я лично использовал шаблоны для обработки нескольких типов контейнеров, а не только для работы с векторами. Я нашел аналогичный пример в Интернете (не помню, где), так что заслуга принадлежит тому, от кого я это украл. Этот конкретный шаблон, похоже, также обрабатывает необработанные массивы.
источник
Используя Newton C ++, это проще, самодокументировано и быстрее, чем с std :: find, потому что возвращает bool напрямую.
Я думаю, что очевидно, что делают функции.
источник