Std :: ভেক্টরে কোনও আইটেম উপস্থিত রয়েছে কীভাবে তা আবিষ্কার করবেন?


616

আমি যা করতে চাই তা হ'ল ভেক্টরে কোনও উপাদান রয়েছে কিনা তা যাচাই করা, যাতে আমি প্রতিটি ক্ষেত্রে মোকাবেলা করতে পারি।

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

2
ভেক্টরের সন্ধান খুব ধীর গতি থেকে আপনি ভেক্টরের প্রতিটি একক উপাদানকে দেখতে হবে তাই যদি আপনি অনেকগুলি
নজরদারি

7
@ এনামচো: ভেক্টর বাছাই করা থাকলে নীচে পোস্ট করা হিসাবে সবসময় বাইনারি অনুসন্ধান থাকে। এটি এটিকে মানচিত্রের মতো দ্রুততর করে তোলে এবং যদি আপনি কেবল মানগুলি সঞ্চয় করেন (কী / মান মানচিত্র নয়) তবে এটি অনেক কম স্মৃতি ব্যবহার করবে।
অ্যাডাম হাউস

4
মানচিত্র অবশ্যই সেরা পছন্দ নয়, তবে সেট ব্যবহার করা কার্যকর হতে পারে। আপনার যদি ও (1) দেখার সময় প্রয়োজন হয় তবে হ্যাশ_সেটই হ'ল উপায়।
ফিলিপ

একটি ডুপ্লিকেট প্রশ্নে একটি চমত্কার উত্তর বর্তমান: stackoverflow.com/a/3451045/472647
CodeMouse92

1
আপনি যদি বিভিন্ন সংখ্যার জন্য একাধিকবার অনুসন্ধান করতে যাচ্ছেন তবে একটি হ্যাশ টেবিলটি আরও কার্যকর।
এনএল 628

উত্তর:


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
আমি দেখতে পাচ্ছি না যে গণনা () কীভাবে খুঁজে পাওয়া () এর চেয়ে দ্রুত হতে পারে, যেহেতু একটি উপাদান পাওয়া মাত্রই খুঁজে () থামায়, যখন গণনা () সর্বদা পুরো ক্রমটি স্ক্যান করতে হয়।
এরিক ম্যালেনফ্যান্ট

114
ভুলে যাবেন না #include <algorithm>অন্যথায় আপনি খুব অদ্ভুত ত্রুটি পেতে পারেন যেমন 'নেমস্পেস
স্টাডিতে

80
এটি কি কাউকে বিরক্ত করে না যে এসটিএল "অবজেক্ট-ওরিয়েন্টেড" হওয়া সত্ত্বেও .find()এখনও এর সদস্য ফাংশন নয়std::vector , যেমনটি আপনি আশা করেছিলেন যে এটি হওয়া উচিত? আমি ভাবছি যদি এটি কোনওভাবেই টেম্প্লেটিংয়ের পরিণতি হয়।
bobobobo

71
@ বোবোবো: সদস্যদের সাথে বনাম, সদস্যদের সাথে ওওপি-র কোনও সম্পর্ক নেই। এবং এখানে একটি বিস্তৃত চিন্তাভাবনা রয়েছে যে কোনও কিছুতে যদি সদস্য হতে না হয়, বা সদস্য হিসাবে প্রয়োগের সময় এটি কোনও সুবিধা দেয় না, তবে তার সদস্য হওয়া উচিত নয়; std::vector<>::find()কোনও সুবিধা দেয় না, প্রয়োজনও হয় না, সুতরাং এটির সদস্য হওয়া উচিত নয়। আরও দেখুন en.wikedia.org/wiki/Coupling_%28computer_programming%29
সেবাস্তিয়ান মাচ

36
@ ফ্রেসনেল আমি যুক্তি দিয়ে বলব যে "যখন সদস্য হিসাবে প্রয়োগ করার সময় এটি কোনও সুবিধা দেয় না" এই ক্ষেত্রে মিথ্যা। সরলিকৃত এবং পরিষ্কার ইন্টারফেস হওয়ার সুবিধা being উদাহরণস্বরূপ: এর mvec.find(key) != mvec.cend()চেয়ে ভাল std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
সোভেল

113

অন্যরা যেমন বলেছে, এসটিএল findবা find_ifফাংশন ব্যবহার করুন । কিন্তু আপনি যদি ও খুব বড় ভেক্টর মধ্যে অনুসন্ধান করা হয় এই প্রভাব কর্মক্ষমতা, আপনি আপনার ভেক্টর বাছাই এবং তারপর ব্যবহার করতে পারেন binary_search, lower_boundঅথবাupper_bound আলগোরিদিম।


3
ভাল উত্তর! অনুসন্ধান সর্বদা ও (এন) হয়। নিম্ন-গণ্ডিটি হ'ল (লগ (এন)) যদি এলোমেলো-অ্যাক্সেস পুনরায় ব্যবহারকারীর সাথে ব্যবহৃত হয়।
স্টিফেন এডমন্ডস

30
বাছাই করা ও (এনলোগন) যদিও, তবে আপনি ও (লগন) অনুসন্ধানের চেয়ে আরও বেশি অনুসন্ধান করলেই এটি মূল্যবান।
লাইওরি

7
@ লিওরি সত্য যে এটি আপনার ব্যবহারের ধরণগুলির উপর নির্ভর করে। আপনার যদি কেবল একবার এটি বাছাই করা প্রয়োজন তবে বারবার অনেকগুলি অনুসন্ধান এটি আপনাকে বাঁচাতে পারে।
ব্রায়ান নিল

1
@ ব্রায়ান নিল, একটি বড় ভেক্টর বাছাই করা মূল্যবান যদি এর উপর অনেকগুলি উপাদান অনুসন্ধান করতে হয়। বাছাই O (nlogn) হবে এবং ও (এন) ভাল হবে যদি কেবল একবারে কোনও উপাদান খুঁজে পাওয়া যায় :)
স্বপ্নিল বি।

47

Stl এর অ্যালগরিদম শিরোনামটি থেকে অনুসন্ধানটি ব্যবহার করুন I আমি এর ব্যবহারটি টাইপ দিয়ে চিত্রিত করেছি। আপনি যতক্ষণ না সাম্যতার জন্য তুলনা করতে পারেন আপনার পছন্দ মতো কোনও প্রকারের ব্যবহার করতে পারেন (ওভারলোড == আপনার কাস্টম শ্রেণীর জন্য আপনার প্রয়োজন হলে)।

#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 () এছাড়াও উপযুক্ত হতে পারে। এটি সাম্যের পরিবর্তে একটি স্বেচ্ছাসেবক শিকার ব্যবহার করে অনুসন্ধানের অনুমতি দেয়।
এরিক ম্যালেনফ্যান্ট

উফ, আপনার মন্তব্যটি অনেক দেরিতে দেখেছি। আমি যে উত্তরটি দিয়েছি তা ফাইন্ড_আইফেরও উল্লেখ করে।
ফ্রাঙ্ক

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
}

বাইনারি অনুসন্ধান ও (লগ এন) সবচেয়ে খারাপ ক্ষেত্রে পারফরম্যান্স দেয় যা প্রথম পদ্ধতির চেয়ে বেশ দক্ষ efficient বাইনারি অনুসন্ধান ব্যবহার করার জন্য, আপনি আদেশটি দেওয়ার গ্যারান্টি দেওয়ার জন্য প্রথমে ভেক্টরকে বাছাই করার জন্য Qsort ব্যবহার করতে পারেন।


3
মানে না std::sort? qsortভেক্টরগুলিতে খুব অদক্ষ .... দেখুন: স্ট্যাকওভারফ্লো.com
জেসন আর মিক

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
টাইপনেমগুলি

@ এরিক অ্যারোনাস্টি যদি আপনি value_typeউপাদান ধরণের জন্য ধারক থেকে ব্যবহার করেন তবে আপনি 1 টি টেম্পলেট যুক্তি দিয়ে সরে যেতে পারেন । আমি এর মতো একটি উত্তর যুক্ত করেছি।
মার্টিন ব্রডহর্স্ট

13

সি ++ 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।
andreee

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
মনে রাখবেন এটি কখনও কখনও কিছুটা বিস্তৃত হয় - উদাহরণস্বরূপ এটি স্ট্যান্ড :: সেট এর পক্ষে কাজ করবে তবে সন্ধানী () সদস্য ফাংশনের তুলনায় ভয়ানক পারফরম্যান্স দিন। দ্রুত অনুসন্ধানের (ধারক / মানচিত্র,
নিবন্ধহীন_

10

মনে রাখবেন যে, আপনি যদি অনেকগুলি অনুসন্ধান করতে যাচ্ছেন তবে এমন এসটিএল পাত্রে রয়েছে যে এটির জন্য ভাল। আপনার অ্যাপ্লিকেশন কী তা আমি জানি না, তবে এসটিডি :: মানচিত্রের মতো সাহসী পাত্রগুলি বিবেচনা করার মতো হতে পারে।

std :: ভেক্টর হ'ল পছন্দের ধারক না হয়ে থাকে যদি না আপনি অন্য কারার কারণ হয়ে থাকেন এবং মান অনুসারে অনুসন্ধানগুলি এর কারণ হতে পারে।


এমনকি মান অনুসারে অনুসন্ধানের সাথে ভেক্টর একটি ভাল পছন্দ হতে পারে, যতক্ষণ না এটি বাছাই করা হয় এবং আপনি বাইনারি_সার্ক, লোয়ার_বাউন্ড বা আপার_বাউন্ড ব্যবহার করেন। যদি ধারকগুলির বিষয়বস্তুগুলি চেহারাগুলির মধ্যে পরিবর্তিত হয় তবে ভেক্টর খুব ভাল নয় কারণ পুনরায় বাছাই করার প্রয়োজন রয়েছে।
রেনজে দে ওয়াল

8

এসটিএল অনুসন্ধানটি ব্যবহার করুন ফাংশন।

মনে রাখবেন যে একটি সন্ধান_আইএফ ফাংশন রয়েছে, যা আপনার অনুসন্ধান আরও জটিল হলে আপনি ব্যবহার করতে পারেন, উদাহরণস্বরূপ, যদি আপনি কেবল কোনও উপাদান অনুসন্ধান করেন না, তবে উদাহরণস্বরূপ, এমন কোনও উপাদান রয়েছে যা নির্দিষ্ট কিছু পূরণ করে কিনা তা দেখতে চান শর্ত, উদাহরণস্বরূপ, একটি স্ট্রিং যা "abc" দিয়ে শুরু হয়। ( 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

সি ++ অপারেটর ব্যবহার করে অন্য একটি নমুনা।

#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

আমি ব্যক্তিগতভাবে কেবলমাত্র ভেক্টরদের সাথে ডিল করার পরিবর্তে একাধিক ধরণের পাত্রে হ্যান্ডেল করার জন্য দেরির টেমপ্লেটগুলি ব্যবহার করেছি। আমি অনলাইনে একটি অনুরূপ উদাহরণ খুঁজে পেয়েছি (কোথায় তা মনে করতে পারে না) তাই যার যার কাছ থেকে আমি এটি চালিয়েছি তার creditণ যায়। এই নির্দিষ্ট প্যাটার্নটি কাঁচা অ্যারেগুলিও হ্যান্ডেল করে বলে মনে হচ্ছে।

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();
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.