私がやりたいのは、要素がベクトルに存在するかどうかを確認することだけなので、それぞれの場合に対処できます。
if ( item_present )
do_this();
else
do_that();
私がやりたいのは、要素がベクトルに存在するかどうかを確認することだけなので、それぞれの場合に対処できます。
if ( item_present )
do_this();
else
do_that();
回答:
std::find
から使用できます<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に一致する関数が見つからない」などの非常に奇妙なエラーが発生する可能性があることを忘れないでください
.find()
あるにも関わらず、のメンバー関数ではないことを誰も気にしませんでしたstd::vector
か?これはどういうわけかテンプレートの結果だと思います。
std::vector<>::find()
会員になることはできません。そのため、会員になることもできません。en.wikipedia.org/wiki/Coupling_%28computer_programming%29
mvec.find(key) != mvec.cend()
がに適していstd::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
ます。
他の人が言ったように、STL find
またはfind_if
関数を使用します。あなたは非常に大きなベクトルと、この影響を与えるパフォーマンスで検索されている場合でも、あなたはあなたのベクトルをソートし、次に使用する場合がありbinary_search
、lower_bound
またはupper_bound
アルゴリズムを。
stlのアルゴリズムヘッダーからfindを使用します。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を使用して最初にベクターを並べ替え、順序付けを保証することができます。
私はこのようなものを使用します...
#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
要素タイプのコンテナーから使用する場合、@ ErikAronestyは1つのテンプレート引数で回避できます。このような答えを追加しました。
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は非推奨と完全にC ++ 17で除去しました。代わりにbind
with placeholders
および/またはlambdasを使用してください。
以下は、任意のコンテナで機能する関数です。
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
コンテナからを抽出できるため、1つのテンプレートパラメータで済むことに注意してください。あなたは必要とするtypename
ためでContainer::value_type
ある依存名。
多くのルックアップを行う場合は、そのためのSTLコンテナがあることを覚えておいてください。あなたのアプリケーションが何であるかはわかりませんが、std :: mapのような連想コンテナは検討に値するかもしれません。
std :: vectorは、別の理由がない限り、最適なコンテナであり、値による検索がそのような理由になる可能性があります。
ブーストで使用できます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()
}
countも使用できます。これは、ベクター内に存在するアイテムの数を返します。
int t=count(vec.begin(),vec.end(),item);
find
count
最初の一致後はカウントし続けないため、はより高速です。
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以降):
使える 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;
}
また、一部の検索アルゴリズムを渡す柔軟性もあります。こちらをご参照ください。
私は最近、ベクトルだけを扱うのではなく、複数のタイプのコンテナーを一度に処理するために、最近のテンプレートを使用しました。私は同様の例をオンラインで見つけました(どこで思い出せないか)。この特定のパターンは、生の配列も処理するようです。
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);
}
Newton C ++を使用すると、ブール値を直接返すため、std :: findを使用するよりも簡単で、自己文書化され、高速です。
bool exists_linear( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
bool exists_binary( INPUT_ITERATOR first, INPUT_ITERATOR last, const T& value )
関数が何をするかは明らかだと思います。
include <newton/algorithm/algorithm.hpp>
if ( newton::exists_linear(first, last, value) )
do_this();
else
do_that();