यह कैसे पता लगाया जाए कि कोई वस्तु std :: वेक्टर में मौजूद है?


616

मैं केवल यह जांचना चाहता हूं कि वेक्टर में कोई तत्व मौजूद है या नहीं, इसलिए मैं प्रत्येक मामले से निपट सकता हूं।

if ( item_present )
   do_this();
else
   do_that();

2
वेक्टर में खोज बहुत धीमी है क्योंकि आपको वेक्टर के हर एक तत्व को देखना है, इसलिए यदि आप बहुत सारे लुकअप कर रहे हैं तो मैप का उपयोग करने पर विचार करें
naumcho

7
@naumcho: यदि वेक्टर को सॉर्ट किया जाता है, तो हमेशा बाइनरी खोज होती है, जैसा कि नीचे पोस्ट किया गया है। यह इसे मानचित्र के रूप में तेज़ बनाता है और यदि आप केवल मान संग्रहीत कर रहे हैं (कुंजी / मान मानचित्र नहीं) तो यह बहुत कम मेमोरी का उपयोग करने वाला है।
एडम हैव्स

4
नक्शे निश्चित रूप से सबसे अच्छा विकल्प नहीं हैं, लेकिन सेट का उपयोग करना उपयोगी हो सकता है। यदि आपको O (1) लुकअप समय चाहिए, तो hash_set जाने का रास्ता है।
फिलीपिंस

डुप्लीकेट प्रश्न पर मौजूद शानदार उत्तर: stackoverflow.com/a/3451045/472647
CodeMouse92

1
यदि आप विभिन्न संख्याओं के लिए कई बार खोजने जा रहे हैं, तो एक हैश तालिका अधिक कुशल होगी।
NL628

जवाबों:


915

आप 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();

216
मैं नहीं देखता कि कैसे गणना () खोज की तुलना में तेज़ हो सकती है (), क्योंकि एक तत्व मिलते ही ढूंढना () बंद हो जाता है, जबकि गिनती () में हमेशा पूरे अनुक्रम को स्कैन करना होता है।
9ric Malenfant

114
#include <algorithm>
Might

80
क्या इसने किसी को परेशान नहीं किया है कि एसटीएल "ऑब्जेक्ट-ओरिएंटेड" होने के बावजूद, .find()अभी भी इसका सदस्य कार्य नहीं है std::vector, जैसा कि आप चाहते हैं कि यह होना चाहिए? मुझे आश्चर्य है कि अगर यह किसी भी तरह का परिणाम है।
बोब्बोबो

71
@ बोबोबोबो: ओओपी का सदस्यों बनाम गैर-सदस्यों से कोई लेना-देना नहीं है। और विचार का एक व्यापक स्कूल है कि अगर किसी सदस्य को सदस्य होने के लिए कुछ नहीं करना है, या जब वह सदस्य के रूप में लागू नहीं होता है, तो वह सदस्य नहीं होना चाहिए; 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()
20

113

जैसा कि दूसरों ने कहा है, एसटीएल findया find_ifकार्यों का उपयोग करें । लेकिन अगर आप और इस प्रभावों प्रदर्शन बहुत बड़ी वैक्टर में खोज कर रहे हैं, तो आप अपने वेक्टर सॉर्ट करने के लिए चाहते हो सकता है और उसके बाद का उपयोग binary_search, lower_boundया upper_boundएल्गोरिदम।


3
अच्छा उत्तर! ढूँढें हमेशा o (n) है। यदि रैंडम-एक्सेस पुनरावृत्तियों के साथ उपयोग किया जाता है तो निचला_बाउंड ओ (लॉग (एन)) है।
स्टीफन एडमंड्स

30
सॉर्टिंग हालांकि O (nlogn) है, इसलिए यदि आप O (logn) खोजों से अधिक कर रहे हैं, तो यह केवल योग्य है।
लियोरी

7
@ लियोरी ट्रू यह आपके उपयोग पैटर्न पर निर्भर करता है। यदि आपको केवल एक बार इसे क्रमबद्ध करने की आवश्यकता है, तो बार-बार कई खोजों को यह आपको बचा सकता है।
ब्रायन नील

1
@ ब्रायन नील, एक बड़े वेक्टर को छांटने लायक है, अगर उस पर कई तत्व खोजे जाने चाहिए। सॉर्टिंग O (nlogn) होगा और O (n) बेहतर होगा यदि किसी को केवल एक बार तत्व ढूंढना है :)
स्वप्निल बी।

47

Stl के एल्गोरिथ्म हेडर से खोज का उपयोग करें। मैंने इंट टाइप के साथ इसके उपयोग का वर्णन किया है। आप किसी भी प्रकार का उपयोग कर सकते हैं जब तक आप समानता के लिए तुलना कर सकते हैं (अधिभार == यदि आपको अपने कस्टम वर्ग के लिए आवश्यक है)।

#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;
}

2
ओपी की जरूरतों के आधार पर, find_if () भी उपयुक्त हो सकता है। यह समानता के बजाय एक मनमाना विधेय का उपयोग करके खोज करने की अनुमति देता है।
9ric Malenfant

उफ़, आपकी टिप्पणी को बहुत देर से देखा। मैंने जो उत्तर दिया, उसमें find_if का भी उल्लेख है।
फ्रैंक

39

यदि आपका वेक्टर ऑर्डर नहीं किया गया है, तो जिस दृष्टिकोण का सुझाव दिया गया है उसका उपयोग करें:

if(std::find(vector.begin(), vector.end(), item)!=vector.end()){
      // Found the item
}

यदि आपका वेक्टर ऑर्डर किया गया है, तो बाइनरी_सर्च विधि का उपयोग करें ब्रायन नील का सुझाव दिया गया है:

if(binary_search(vector.begin(), vector.end(), item)){
     // Found the item
}

बाइनरी खोज पैदावार ओ (लॉग एन) सबसे खराब स्थिति वाला प्रदर्शन है, जो पहले दृष्टिकोण की तुलना में अधिक कुशल है। द्विआधारी खोज का उपयोग करने के लिए, आप आदेश देने के लिए सबसे पहले वेक्टर को सॉर्ट करने के लिए qsort का उपयोग कर सकते हैं।


3
क्या आपका मतलब नहीं है std::sort? qsortवैक्टर पर बहुत अक्षम है .... देखें: stackoverflow.com/questions/12308243/…
जेसन आर। मिक

1
बाइनरी खोज बड़े कंटेनरों के लिए बेहतर प्रदर्शन करेगी, लेकिन छोटे कंटेनरों के लिए एक सरल रैखिक खोज के रूप में तेज, या तेज होने की संभावना है।
बिलटी

21

मैं कुछ इस तरह का उपयोग ...

#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 टाइपनामों का उपयोग करके सूचियों या वैक्टर के लिए काम कर सकते हैं
एरिक

@ErikAronesty आप value_typeतत्व प्रकार के लिए कंटेनर से उपयोग करने पर 1 टेम्पलेट तर्क के साथ दूर हो सकते हैं । मैंने इस तरह से एक उत्तर जोड़ा है।
मार्टिन ब्रॉडहर्स्ट

13

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();

1
bind1stऔर bind2ndकर रहे हैं सी के बाद से ++ 11 पदावनत और पूरी तरह से C ++ 17 हटा दिया। का प्रयोग करें bindसाथ placeholdersऔर / या बजाय lambdas।
एंड्री

11

यहां एक फ़ंक्शन है जो किसी भी कंटेनर के लिए काम करेगा:

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एक आश्रित नाम है


5
ध्यान दें कि यह कभी-कभी थोड़ा बहुत व्यापक होता है - यह std के लिए काम करेगा :: उदाहरण के लिए सेट करें, लेकिन खोज () सदस्य फ़ंक्शन की तुलना में भयानक प्रदर्शन दें। मैंने कंटेनरों के लिए एक तेज़ खोज (सेट / मैप, unordered_ *) के साथ विशेषज्ञता जोड़ना सबसे अच्छा पाया है
एंडी क्राउवेल

10

ध्यान रखें कि, यदि आप बहुत सारे लुकअप करने जा रहे हैं, तो एसटीएल कंटेनर हैं जो इसके लिए बेहतर हैं। मुझे नहीं पता कि आपका आवेदन क्या है, लेकिन एसटीडी :: मानचित्र जैसे सहयोगी कंटेनर विचार करने योग्य हो सकते हैं।

std :: वेक्टर पसंद का कंटेनर है जब तक कि आपके पास दूसरे के लिए कोई कारण नहीं है, और मूल्य के अनुसार लुकअप ऐसा कारण हो सकता है।


मूल्य से लुकअप के साथ भी वेक्टर एक अच्छा विकल्प हो सकता है, जब तक कि इसे सॉर्ट किया जाता है और आप बाइनरी_सर्च, लोअरबाउंड या अपर_बाउंड का उपयोग करते हैं। यदि कंटेनर की सामग्री लुकअप के बीच बदल जाती है, तो वेक्टर फिर से छांटने की आवश्यकता के कारण बहुत अच्छा नहीं है।
डीएएल का नवीनीकरण करें

8

एसटीएल खोज का उपयोग करें कार्य करते हैं।

ध्यान रखें कि एक find_if फ़ंक्शन भी है , जिसका उपयोग आप कर सकते हैं यदि आपकी खोज अधिक जटिल है, अर्थात यदि आप केवल एक तत्व की तलाश नहीं कर रहे हैं, लेकिन, उदाहरण के लिए, देखें कि क्या कोई ऐसा तत्व है जो किसी निश्चित को पूरा करता है स्थिति, उदाहरण के लिए, एक स्ट्रिंग जो "एबीसी" से शुरू होती है। ( find_ifआपको एक पुनरावृत्ति देगा जो पहले ऐसे तत्व को इंगित करता है)।


7

बढ़ावा देने के साथ आप उपयोग कर सकते हैं any_of_equal:

#include <boost/algorithm/cxx11/any_of.hpp>

bool item_present = boost::algorithm::any_of_equal(vector, element);

5

आप इस कोड को आज़मा सकते हैं:

#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()
}

3

आप findफ़ंक्शन का उपयोग कर सकते हैं , stdनामस्थान में पाया जाता है , अर्थात std::find। आप जिस वेक्टर को खोजना चाहते हैं, उस std::findफ़ंक्शन beginऔर endइट्रेटर को पास करते हैं, साथ ही उस तत्व के साथ जिसे आप खोज रहे हैं और वेक्टर के अंत के परिणामस्वरूप परिणामी की तुलना करके देखें कि वे मेल खाते हैं या नहीं।

std::find(vector.begin(), vector.end(), item) != vector.end()

आप भी उस पुनरावृत्ति को रोकने में सक्षम हैं और किसी भी अन्य पुनरावृत्त की तरह इसे सामान्य रूप से उपयोग करते हैं।


3

आप गिनती का भी उपयोग कर सकते हैं। यह एक वेक्टर में मौजूद वस्तुओं की संख्या लौटाएगा।

int t=count(vec.begin(),vec.end(),item);

11
findसे तेज है count, क्योंकि यह पहले मैच के बाद की गिनती में नहीं है।
केमिली गौडेय्यून

2

यदि आप वेक्टर में एक स्ट्रिंग ढूंढना चाहते हैं:

    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));

2

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!");
  }
}

4
मैं ऑपरेटर को इस तरह से ओवरलोडिंग को रोकने की सलाह नहीं दूंगा।
लियोन

2
लियोन, मैं आपसे सहमत हूं, शब्दार्थ यह सही नहीं है। मैं इसका उपयोग इकाई परीक्षणों को अधिक स्पष्ट रूप से करने के लिए करता हूं।
वल्देमार_रुडोल्फ़ोविच

1
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;
}

1

(सी ++ 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;
}

इसके अलावा कुछ खोज एल्गोरिदम को पारित करने का लचीलापन है। यहाँ देखें।

https://en.cppreference.com/w/cpp/algorithm/search


1

मैंने व्यक्तिगत रूप से केवल वैक्टर से निपटने के बजाय कई प्रकार के कंटेनरों को संभालने के लिए देर से टेम्पलेट्स का उपयोग किया है। मुझे एक ऐसा ही उदाहरण ऑनलाइन मिला (याद नहीं कर सकते कि वह कहां है) इसलिए इसका श्रेय जिस किसी को भी जाता है, मैंने इसे हासिल कर लिया है। यह विशेष पैटर्न कच्चे सरणियों को भी संभालने के लिए लगता है।

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);
}

-4

न्यूटन सी ++ का उपयोग करना आसान है, स्व-प्रलेखित और एसटीडी की तुलना में तेज :: सीधे बूल वापस करने के कारण खोजें।

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();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.