Tudo o que quero fazer é verificar se existe um elemento no vetor ou não, para que eu possa lidar com cada caso.
if ( item_present )
do_this();
else
do_that();
Tudo o que quero fazer é verificar se existe um elemento no vetor ou não, para que eu possa lidar com cada caso.
if ( item_present )
do_this();
else
do_that();
Respostas:
Você pode usar std::find
em <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()
Isso retorna um bool ( true
se presente, false
caso contrário). Com o seu exemplo:
#include <algorithm>
#include <vector>
if ( std::find(vec.begin(), vec.end(), item) != vec.end() )
do_this();
else
do_that();
#include <algorithm>
ou então você pode obter erros muito estranhos como 'não consegue encontrar função correspondente no std namespace'
.find()
ainda não é uma função membro std::vector
, como seria de esperar? Eu me pergunto se isso é de alguma forma uma conseqüência do modelo.
std::vector<>::find()
não daria nenhuma vantagem, nem é necessário; portanto, não, não deve ser um membro. Veja também en.wikipedia.org/wiki/Coupling_%28computer_programming%29
mvec.find(key) != mvec.cend()
é preferível std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
.
Como outros já disseram, use o STL find
ou find_if
funções. Mas se você está procurando em grandes vetores e isso afeta o desempenho, você pode querer classificar seu vetor e use as binary_search
, lower_bound
ou upper_bound
algoritmos.
Use find do cabeçalho do algoritmo de stl. Ilustrei seu uso com o tipo int. Você pode usar qualquer tipo que quiser, desde que possa comparar a igualdade (sobrecarga == se for necessário para sua classe personalizada).
#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;
}
Se seu vetor não for solicitado, use a abordagem sugerida pelo MSN:
if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
// Found the item
}
Se seu vetor for encomendado, use o método binary_search sugerido por Brian Neal:
if(binary_search(vector.begin(), vector.end(), item)){
// Found the item
}
a pesquisa binária produz O (log n) pior desempenho, o que é muito mais eficiente que a primeira abordagem. Para usar a pesquisa binária, você pode usar qsort para classificar o vetor primeiro e garantir que ele seja ordenado.
std::sort
? qsort
é muito ineficiente em vetores .... ver: stackoverflow.com/questions/12308243/...
Eu uso algo assim ...
#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
... dessa forma, é realmente claro e legível. (Obviamente, você pode reutilizar o modelo em vários locais).
value_type
o contêiner para o tipo de elemento. Eu adicionei uma resposta como esta.
No C ++ 11 você pode usar any_of
. Por exemplo, se for um vector<string> v;
então:
if (any_of(v.begin(), v.end(), bind(equal_to<string>(), _1, item)))
do_this();
else
do_that();
Como alternativa, use uma lambda:
if (any_of(v.begin(), v.end(), [&](const std::string& elem) { return elem == item; }))
do_this();
else
do_that();
bind1st
e bind2nd
foram descontinuados desde C ++ 11 e completamente removidos em C ++ 17. Use bind
com placeholders
e / ou lambdas.
Aqui está uma função que funcionará para qualquer contêiner:
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();
}
Observe que você pode se safar com 1 parâmetro de modelo porque pode extrair o value_type
do Container. Você precisa do typename
porque Container::value_type
é um nome dependente .
Lembre-se de que, se você estiver fazendo muitas pesquisas, existem contêineres STL que são melhores para isso. Não sei qual é a sua aplicação, mas vale a pena considerar contêineres associativos como std :: map.
std :: vector é o contêiner de escolha, a menos que você tenha uma razão para outra e as pesquisas por valor possam ser essa.
Use a função de localização STL .
Lembre-se de que também existe uma função find_if , que você pode usar se sua pesquisa for mais complexa, ou seja, se você não estiver apenas procurando por um elemento, mas, por exemplo, desejar ver se há um elemento que atenda a um determinado condição, por exemplo, uma sequência que começa com "abc". ( find_if
daria a você um iterador que aponta para o primeiro elemento desse tipo).
Com o boost você pode usar any_of_equal
:
#include <boost/algorithm/cxx11/any_of.hpp>
bool item_present = boost::algorithm::any_of_equal(vector, element);
Você pode tentar este código:
#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()
}
Você pode usar a find
função, encontrada no std
espaço para nome, ie std::find
. Você passa a std::find
função begin
e o end
iterador do vetor que deseja pesquisar, junto com o elemento que você está procurando e compara o iterador resultante ao final do vetor para ver se eles correspondem ou não.
std::find(vector.begin(), vector.end(), item) != vector.end()
Você também pode desreferenciar esse iterador e usá-lo normalmente, como qualquer outro iterador.
Você pode usar count também. Ele retornará o número de itens presentes em um vetor.
int t=count(vec.begin(),vec.end(),item);
find
é mais rápido que count
, porque não continua contando após a primeira partida.
Se você quiser encontrar uma string em um vetor:
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));
Outro exemplo usando operadores 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 e superior):
pode usar std::search
também
Isso também é útil para pesquisar a sequência de elementos.
#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;
}
Também há flexibilidade de passar alguns algoritmos de busca. Consulte aqui.
Pessoalmente, usei modelos tarde para lidar com vários tipos de contêineres de uma só vez, em vez de lidar apenas com vetores. Encontrei um exemplo semelhante on-line (não me lembro de onde), então o crédito é para quem quer que tenha roubado isso. Esse padrão específico parece lidar com matrizes brutas também.
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);
}
Usando o Newton C ++ , é mais fácil, auto-documentado e mais rápido do que com o std :: find devido ao retorno de um bool diretamente.
bool exists_linear( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
bool exists_binary( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
Eu acho que é óbvio o que as funções fazem.
include <newton/algorithm/algorithm.hpp>
if ( newton::exists_linear(first, last, value) )
do_this();
else
do_that();