Todo lo que quiero hacer es verificar si un elemento existe en el vector o no, para poder tratar cada caso.
if ( item_present )
do_this();
else
do_that();
Todo lo que quiero hacer es verificar si un elemento existe en el vector o no, para poder tratar cada caso.
if ( item_present )
do_this();
else
do_that();
Respuestas:
Puedes usar std::find
desde <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()
Esto devuelve un bool ( true
si está presente, de lo false
contrario). Con tu ejemplo:
#include <algorithm>
#include <vector>
if ( std::find(vec.begin(), vec.end(), item) != vec.end() )
do_this();
else
do_that();
#include <algorithm>
o de lo contrario podrías obtener errores muy extraños como 'no se puede encontrar la función de coincidencia en el espacio de nombres
.find()
todavía no es una función miembro std::vector
, como cabría esperar? Me pregunto si esto es de alguna manera una consecuencia de la plantilla.
std::vector<>::find()
no daría ninguna ventaja, ni es necesaria, por lo tanto, no, no debería ser miembro. Ver también en.wikipedia.org/wiki/Coupling_%28computer_programming%29
mvec.find(key) != mvec.cend()
es preferible a std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
.
Como otros han dicho, use el STL find
o las find_if
funciones. Pero si usted está buscando en grandes vectores y esto afecta al rendimiento, es posible que desee ordenar su vector y luego usar las binary_search
, lower_bound
o upper_bound
algoritmos.
Use find desde el encabezado del algoritmo de stl. He ilustrado su uso con int type. Puede usar cualquier tipo que desee siempre y cuando pueda comparar la igualdad (sobrecarga == si lo necesita para su clase 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;
}
Si su vector no está ordenado, utilice el enfoque sugerido por MSN:
if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
// Found the item
}
Si su vector está ordenado, use el método binary_search que Brian Neal sugirió:
if(binary_search(vector.begin(), vector.end(), item)){
// Found the item
}
la búsqueda binaria produce O (log n) en el peor de los casos, que es mucho más eficiente que el primer enfoque. Para usar la búsqueda binaria, puede usar qsort para ordenar el vector primero y garantizar que esté ordenado.
std::sort
? qsort
es muy ineficiente en vectores ... ver: stackoverflow.com/questions/12308243/…
Yo uso algo como esto ...
#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
... de esa manera es realmente claro y legible. (Obviamente, puede reutilizar la plantilla en varios lugares).
value_type
desde el contenedor para el tipo de elemento. He agregado una respuesta como esta.
En C ++ 11 puedes usar any_of
. Por ejemplo, si es un vector<string> v;
entonces:
if (any_of(v.begin(), v.end(), bind(equal_to<string>(), _1, item)))
do_this();
else
do_that();
Alternativamente, use una lambda:
if (any_of(v.begin(), v.end(), [&](const std::string& elem) { return elem == item; }))
do_this();
else
do_that();
bind1st
y bind2nd
están en desuso desde C ++ 11 y se eliminan por completo en C ++ 17. Use bind
con placeholders
y / o lambdas en su lugar.
Aquí hay una función que funcionará para cualquier contenedor:
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();
}
Tenga en cuenta que puede salirse con 1 parámetro de plantilla porque puede extraerlo value_type
del Contenedor. Necesita el typename
porque Container::value_type
es un nombre dependiente .
Tenga en cuenta que, si va a hacer muchas búsquedas, hay contenedores STL que son mejores para eso. No sé cuál es su aplicación, pero vale la pena considerar los contenedores asociativos como std :: map.
std :: vector es el contenedor de elección a menos que tenga una razón para otra, y las búsquedas por valor pueden ser tal razón.
Use la función de búsqueda STL .
Tenga en cuenta que también existe una función find_if , que puede usar si su búsqueda es más compleja, es decir, si no solo está buscando un elemento, sino que, por ejemplo, desea ver si hay un elemento que cumple un cierto condición, por ejemplo, una cadena que comienza con "abc". ( find_if
le daría un iterador que apunta al primer elemento).
Con boost puedes usar any_of_equal
:
#include <boost/algorithm/cxx11/any_of.hpp>
bool item_present = boost::algorithm::any_of_equal(vector, element);
Puedes probar 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()
}
Puede usar la find
función, que se encuentra en el std
espacio de nombres, es decir std::find
. Pasa la std::find
función the begin
y end
iterator del vector que desea buscar, junto con el elemento que está buscando y compara el iterador resultante con el final del vector para ver si coinciden o no.
std::find(vector.begin(), vector.end(), item) != vector.end()
También puede desreferenciar ese iterador y usarlo de manera normal, como cualquier otro iterador.
Puedes usar count también. Devolverá el número de elementos presentes en un vector.
int t=count(vec.begin(),vec.end(),item);
find
es más rápido que count
, porque no sigue contando después del primer partido.
Si quieres encontrar una cadena en un vector:
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));
Otra muestra 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 y superior):
puede usar std::search
también
Esto también es útil para buscar la secuencia 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;
}
También hay flexibilidad para pasar algunos algoritmos de búsqueda. Consulte aquí
Personalmente, he usado plantillas en los últimos tiempos para manejar múltiples tipos de contenedores a la vez en lugar de tratar solo con vectores. Encontré un ejemplo similar en línea (no recuerdo dónde), así que el crédito va a quien sea que haya robado esto. Este patrón particular parece manejar también las matrices en bruto.
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);
}
Usar Newton C ++ es más fácil, auto documentado y más rápido que con std :: find debido a que devuelve un bool directamente.
bool exists_linear( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
bool exists_binary( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
Creo que es obvio lo que hacen las funciones.
include <newton/algorithm/algorithm.hpp>
if ( newton::exists_linear(first, last, value) )
do_this();
else
do_that();