কোনও উপাদান একটি স্টাডি :: সেটে আছে কীভাবে তা পরীক্ষা করবেন?


329

আপনি কীভাবে পরীক্ষা করতে পারেন যে একটি উপাদান একটি সেটে রয়েছে?

নিম্নলিখিত কোডের একটি সহজ সমতুল্য আছে:

myset.find(x) != myset.end()

4
এর চেয়ে সহজ হওয়ার একমাত্র উপায় হ'ল বুলিয়ান প্রিডিকেট: টেমপ্লেট <টাইপনেম টি> বুল সদস্য (টি কনস্ট্যান্ড এবং আইটেম)। আপনি যে লাইনের বিষয়ে জিজ্ঞাসা করছেন তার শর্তেই এটি (কভারগুলির নীচে) প্রয়োগ করা হবে।
ডন ওয়েকফিল্ড

উত্তর:


399

টিপিক্যাল উপায় যেমন অনেক Stl পাত্রে অস্তিত্ব জন্য চেক করতে std::map, std::set... হল:

const bool is_in = container.find(element) != container.end();

25
এটি সেট এবং মানচিত্রের জন্য নির্দিষ্ট। ভেক্টর, তালিকাগুলি ইত্যাদির কোনও সন্ধানী সদস্যের কার্যকারিতা নেই।
উইলহেমটেল

8
আইএমও গণনা () ব্যবহার করা আরও ভাল কারণ এটি কেবল খাটো এবং এটি পিটারের উত্তরে উল্লিখিত রূপে রূপান্তরিত হয়। আমি বুঝতে পারছি না কেন এই উত্তর গৃহীত হয়েছে এবং
এতগুলি

4
সম্পূর্ণতার স্বার্থে জন্য: ভেক্টর / করণীয় তালিকা এসটিডি ব্যবহার করতে পারেন :: খুঁজে পেয়েছেন: std::find(container.begin(), container.end(), element) != container.end(); ও (এন) সমস্যাটি অবশ্যই রয়ে গেছে ...
অ্যাকোনকাগুয়া

10
@ মিশেলম্যাথিউজ আপনার বৈকল্পিকের সাথে: if(container.find(foo) == container.end())উপাদানটি প্রথমে সন্ধানের জন্য গাছের অনুসন্ধান করতে হবে - যদি এটি পাওয়া না যায় তবে সঠিক সন্নিবেশের অবস্থানটি খুঁজতে আপনাকে দ্বিতীয় গাছের অনুসন্ধান করতে হবে। মূল বৈকল্পিকটির আকর্ষণটি if(container.insert(foo).second) {...}রয়েছে যে এটির জন্য কেবল একটি একক গাছ দেখার প্রয়োজন ...
অ্যাকোনকাগুয়া

23
এমন একটি আছে যা set.contains(x)সি ++ 20 স্ট্যান্ডার্ডে একটি বিল দেয়। আমি জানি না কেন এটি পেতে যে 2020 পর্যন্ত আমাদের নেয়া হচ্ছে।
gremwell

215

কোনও উপাদান উপস্থিত রয়েছে কিনা তা সহজভাবে জানার অন্য উপায় হ'ল চেক করা count()

if (myset.count(x)) {
   // x is in the set, count is 1
} else {
   // count zero, i.e. x not in the set
}

তবে বেশিরভাগ সময়, আমি নিজেকে যেখানেই উপাদানটির অস্তিত্বের জন্য যাচাই করি সেখানে অ্যাক্সেসের প্রয়োজন মনে করি।

সুতরাং আমি যাই হোক না কেন পুনরুক্তি খুঁজে পেতে হবে। তারপরে অবশ্যই এটির সাথে তুলনা করা ভাল end

set< X >::iterator it = myset.find(x);
if (it != myset.end()) {
   // do something with *it
}

সি ++ 20

সি ++ তে 20 সেটে একটি containsক্রিয়াকলাপ পাওয়া যায়, সুতরাং নিম্নলিখিতটি উল্লেখ করা সম্ভব হয়: https://stackoverflow.com/a/54197839/895245

if (myset.contains(x)) {
  // x is in the set
} else {
  // no x 
}

102
মনে রাখবেন যে count()পরিবর্তে ব্যবহার find()করা কখনও ভাল তবে সম্ভাব্যতর খারাপ হয় না। এটি কারণ find()প্রথম ম্যাচের পরে ফিরে count()আসবে, সর্বদা সমস্ত উপাদানগুলির সাথে পুনরাবৃত্তি করবে।
ফ্রেরিচ রাবাবে

34
@ ফরিচ যা কেবলমাত্র প্রাসঙ্গিক multisetএবং multimapআমি ভেবেছিলাম? এখনও যদিও নির্দেশ :) ভাল
পিটার

83
std :: সেট সাধারণত অর্ডার করা ট্রি কাঠামোর সাহায্যে প্রয়োগ করা হয়, সুতরাং গণনা করুন () এবং অনুসন্ধান করুন () উভয়ই (লগইন) পাবেন। সেটের সমস্ত উপাদানগুলির মধ্যে পুনরাবৃত্তি হবে না।
অ্যালান

14
@ ফ্রেরিচরাবা - আপনি কি নিশ্চিত? যেহেতু কেবলমাত্র setকোনও সদস্যের সাথে মেলে এটি কেবল সম্ভব , তাই পিটারটি বলে যে, এই উপাদানটি প্রথম উপাদান চিহ্নিত করার পরে থামার মতো কার্যকর হবে না? যে কোনও ক্ষেত্রে কার্যকর উত্তর!
ড্যান নিসেনবাউম

14
@ ড্যানিসিসনবাউম হ্যাঁ, আপনি ঠিক বলেছেন (এবং ঠিক তেমনই + পিটার এবং + অ্যালান): স্ট্যান্ডার্ড :: সেট এর জন্য, দুটি ফাংশন পারফরম্যান্সের ক্ষেত্রে সমান। সুতরাং যদিও আমার মন্তব্যের প্রথম অংশটি ( count()কখনই তার চেয়ে দ্রুত হবে না find()) এখনও ধরে, দ্বিতীয় অংশটি প্রকৃতপক্ষে প্রযোজ্য নয় std::set। যাইহোক, আমি অনুমান করি যে আরও একটি যুক্তি পক্ষে পক্ষে তৈরি করা যেতে পারে find(): এটি আরও অভিব্যক্তিপূর্ণ, অর্থাত্ জোর দেয় যে আপনি ঘটনার সংখ্যা গণনা না করে কোনও উপাদান সন্ধান করার চেষ্টা করছেন।
ফ্রেইরিচ রাবাবে

42

কেবল পরিষ্কার করার জন্য, contains()এই ধারক ধরণের মতো কোনও সদস্য না থাকার কারণ হ'ল এটি আপনাকে অক্ষম কোড লেখার জন্য উন্মুক্ত করবে। এই জাতীয় পদ্ধতি সম্ভবত this->find(key) != this->end()অভ্যন্তরীণভাবে কেবলমাত্র করবে , তবে কীটি প্রকৃতপক্ষে উপস্থিত থাকলে আপনি কী করবেন তা বিবেচনা করুন; বেশিরভাগ ক্ষেত্রে আপনি তখন উপাদানটি পেতে এবং এটি দিয়ে কিছু করতে চান। এর অর্থ আপনাকে একটি সেকেন্ড করতে হবে find(), যা অদক্ষ। সরাসরি অনুসন্ধান করা আরও ভাল, যাতে আপনি নিজের ফলাফলটি ক্যাশে করতে পারেন:

auto it = myContainer.find(key);
if (it != myContainer.end())
{
    // Do something with it, no more lookup needed.
}
else
{
    // Key was not present.
}

অবশ্যই, যদি আপনি দক্ষতার বিষয়ে চিন্তা না করেন তবে আপনি সর্বদা নিজের রোল করতে পারেন তবে সেক্ষেত্রে আপনার সম্ভবত সি ++ ব্যবহার করা উচিত নয় ...;)


44
সেট সম্পর্কে কি? সাধারণত আপনার কাছে ইতিমধ্যে উপাদান রয়েছে তবে কেবল এটির মধ্যে রয়েছে কিনা তা
খতিয়ে দেখতে চান

8
এই জাতীয় পদ্ধতিতে কোনও পদ্ধতি / ফাংশন অন্তর্ভুক্ত না হবার এটিই আসল কারণ, বা এটি কেবল আপনার শিক্ষিত অনুমান?
ফ্যাবিও এ 15

3
@FabioA। এটা আমার শিক্ষিত অনুমান।
টিম

1
@ আধামার, ধারাবাহিকতা ঠিক এসটিএল এর শক্তিশালী দিক নয় ... ( list::remove, remove(makes_sense_only_for_vector, iterators)...)
এলাজার লাইবোভিচ

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

13

ইন সি ++ 20 পরিশেষে আমরা কিনবো std::set::containsপদ্ধতি।

#include <iostream>
#include <string>
#include <set>

int main()
{
    std::set<std::string> example = {"Do", "not", "panic", "!!!"};

    if(example.contains("panic")) {
        std::cout << "Found\n";
    } else {
        std::cout << "Not found\n";
    }
}

6

আপনি যদি কোনও containsফাংশন যুক্ত করতে যাচ্ছেন তবে এটি দেখতে এরকম হতে পারে:

#include <algorithm>
#include <iterator>

template<class TInputIterator, class T> inline
bool contains(TInputIterator first, TInputIterator last, const T& value)
{
    return std::find(first, last, value) != last;
}

template<class TContainer, class T> inline
bool contains(const TContainer& container, const T& value)
{
    // This works with more containers but requires std::begin and std::end
    // from C++0x, which you can get either:
    //  1. By using a C++0x compiler or
    //  2. Including the utility functions below.
    return contains(std::begin(container), std::end(container), value);

    // This works pre-C++0x (and without the utility functions below, but doesn't
    // work for fixed-length arrays.
    //return contains(container.begin(), container.end(), value);
}

template<class T> inline
bool contains(const std::set<T>& container, const T& value)
{
    return container.find(value) != container.end();
}

এটি std::setঅন্যান্য এসটিএল ধারক এবং এমনকি স্থির দৈর্ঘ্যের অ্যারেগুলির সাথে কাজ করে:

void test()
{
    std::set<int> set;
    set.insert(1);
    set.insert(4);
    assert(!contains(set, 3));

    int set2[] = { 1, 2, 3 };
    assert(contains(set2, 3));
}

সম্পাদনা:

মন্তব্যে নির্দেশিত হিসাবে, আমি অজান্তেই সি ++ 0 এক্স ( std::beginএবং std::end) তে নতুন একটি ফাংশন ব্যবহার করেছি । এখানে VS2010 এর কাছাকাছি তুচ্ছ বাস্তবায়ন:

namespace std {

template<class _Container> inline
    typename _Container::iterator begin(_Container& _Cont)
    { // get beginning of sequence
    return (_Cont.begin());
    }

template<class _Container> inline
    typename _Container::const_iterator begin(const _Container& _Cont)
    { // get beginning of sequence
    return (_Cont.begin());
    }

template<class _Container> inline
    typename _Container::iterator end(_Container& _Cont)
    { // get end of sequence
    return (_Cont.end());
    }

template<class _Container> inline
    typename _Container::const_iterator end(const _Container& _Cont)
    { // get end of sequence
    return (_Cont.end());
    }

template<class _Ty,
    size_t _Size> inline
    _Ty *begin(_Ty (&_Array)[_Size])
    { // get beginning of array
    return (&_Array[0]);
    }

template<class _Ty,
    size_t _Size> inline
    _Ty *end(_Ty (&_Array)[_Size])
    { // get end of array
    return (&_Array[0] + _Size);
    }

}

1
@ আধামার, এটি আসলে অদক্ষ ছিল , তবে আপনি যে কারণে উল্লেখ করেছেন তা মোটেই নয় not
স্যাম হারওয়েল

@Paul: নিশ্চিত যে আপনার জন্য বিশেষজ্ঞতা অন্তর্ভুক্ত করুন std::set, এবং মনে রাখবেন যে এটি শুধুমাত্র সঠিক যদি শুধুমাত্র জিনিস আপনাকে জানতে হবে অস্তিত্ব।
স্যাম হারওয়েল

@ 280Z28: স্টেট :: শুরু (ধারক)? এটি কী এসটিএল স্ট্যান্ডার্ড? এটি আমার জিসিসিতে সংকলন করে না।
স্টেফানভ

@ স্টেফানভ: হি, এটি সি ++ 0 এক্স এর জন্য নতুন। আমি উপরের আমার সংকলক থেকে বাস্তবায়ন যোগ করেছি।
স্যাম হারওয়েল

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

4

উপাদানটি সন্নিবেশ করার সময় কোনও উপাদান সেট রয়েছে কিনা তাও আপনি পরীক্ষা করতে পারেন। একক উপাদান সংস্করণটি তার সদস্য জুটি সহ একটি জুড়ি ফেরত দেয়: প্রথমে একটি পুনরায় আবরণকারীকে সেট করা হয় সদ্য সন্নিবেশ করা উপাদানটির সাথে বা ইতিমধ্যে সেটে থাকা সমতুল্য উপাদানের দিকে নির্দেশ করে। জোড় :: জোড়ায় দ্বিতীয় উপাদানটি যদি সেট করা থাকে যে কোনও নতুন উপাদান inোকানো হয়েছে বা মিথ্যা যদি কোনও সমমানের উপাদান ইতিমধ্যে বিদ্যমান থাকে।

উদাহরণস্বরূপ: ধরুন সেটটিতে ইতিমধ্যে একটি উপাদান হিসাবে 20 রয়েছে।

 std::set<int> myset;
 std::set<int>::iterator it;
 std::pair<std::set<int>::iterator,bool> ret;

 ret=myset.insert(20);
 if(ret.second==false)
 {
     //do nothing

 }
 else
 {
    //do something
 }

 it=ret.first //points to element 20 already in set.

জোড়ের তুলনায় উপাদানটি নতুন isোকানো থাকলে :: প্রথমে সেটটিতে নতুন উপাদানটির অবস্থান নির্দেশ করবে।


2

আপনার নিজের লিখুন:

template<class T>
bool checkElementIsInSet(const T& elem, const std::set<T>& container)
{
  return container.find(elem) != container.end();
}

4
সবেমাত্র তাই করেছেন: টেমপ্লেট <ক্লাস টি> স্ট্যাটিক ইনলাইন বুল রয়েছে (কনস্ট স্ট্যান্ড :: সেট <টি> & এস, টি এক্স) {রিটার্ন (এসফাইন্ড (এক্স)! = এসেন্ড ()); }
ফুলমিকোটন

4
@ পল স্থিতিশীল বৈশ্বিক ফাংশন তৈরি করবেন না। পরিবর্তে আপনার ফাংশনটি একটি বেনামে নেমস্পেসে রাখুন: এটি সেই ফাংশন তৈরির সি ++ পন্থা যা অন্য সংকলন ইউনিটগুলিতে লিঙ্ক করবে না। এছাড়াও, আপনার টি প্যারামিটারটি কনস্ট-নির্ভুলতা এবং দক্ষতার জন্য একটি কনস্টের রেফারেন্স হওয়া উচিত।
উইলহেমটেল

-1: তাত্পর্যপূর্ণ নয় এবং এসটিএল স্টাইলে মোটেও নয় । এটি ঠিক আছে যদি আপনি এসটিএল ব্যবহার না করেন তবে আপনি যদি এসটিএল ব্যবহার করছেন তবে আপনার কমপক্ষে এর মানগুলি অনুসরণ করার চেষ্টা করা উচিত।
স্যাম হারওয়েল

1
@ 280Z28: আমি দুঃখিত যে আমার কোডটি আপনার মানদণ্ডে নেই, আমি কেবল দেখিয়েছিলাম যে আপনি যদি এসটিএল এর ইন্টারফেস পছন্দ না করেন তবে আপনি নিজের লেখা লিখতে পারেন। জীজ, মুখ্য নয়? এটি কতটা প্রলুব্ধ হতে হবে? আপনার উদাহরণটি দুর্দান্ত দেখায়, এর অর্থ এই নয় যে আমার খারাপ। ওপিতে যেমনটি জিজ্ঞাসা করা হয়েছিল তেমন সেটটিতে এটি আরও বেশি কেন্দ্রীভূত।
স্টেফানভ

1
@ 280Z28: আমি কেবল একটি বিষয় বলছিলাম point আমি ভেবেছিলাম ছবিটি পাওয়ার জন্য লোকেরা যথেষ্ট বুদ্ধিমান হবে।
স্টেফানভ

2

আমি ব্যবহার করি

if(!my_set.count(that_element)) //Element is present...
;

তবে এটি তেমন দক্ষ নয়

if(my_set.find(that_element)!=my_set.end()) ....;

আমার সংস্করণটি কোডটি লেখার ক্ষেত্রে কেবল আমার সময় সাশ্রয় করে। আমি প্রতিযোগিতামূলক কোডিংয়ের জন্য এটিকে পছন্দ করি।


হ্যাঁ count(),। বুলিয়ান এক্সপ্রেশনটিতে ব্যবহৃত পূর্ণসংখ্যা-ফেরত ফাংশনটি শূন্য-অ-শূন্যের জন্য পরীক্ষা করা হচ্ছে তা বুঝতে অক্ষম যে কেউ সি / সি ++ বুদ্ধিমানের দুর্দান্ত সমুদ্রে অনেকগুলি, আরও অনেক ট্র্যাভেল পাবে। এবং, উপরে উল্লিখিত হিসাবে, সেটগুলির জন্য সত্যই দক্ষ হওয়া উচিত, যা ছিল প্রশ্ন।
রন বার্ক

0

আমি এর containsজন্য একটি সাধারণ ফাংশন লিখতে সক্ষম হয়েছি std::listএবং std::vector,

template<typename T>
bool contains( const list<T>& container, const T& elt )
{
  return find( container.begin(), container.end(), elt ) != container.end() ;
}

template<typename T>
bool contains( const vector<T>& container, const T& elt )
{
  return find( container.begin(), container.end(), elt ) != container.end() ;
}

// use:
if( contains( yourList, itemInList ) ) // then do something

এটি সিনট্যাক্সটি কিছুটা সাফ করে।

তবে এই কাজটি স্বেচ্ছাসেবী স্টাইলের পাত্রে তৈরি করতে আমি টেমপ্লেট টেম্পলেট প্যারামিটার যাদু ব্যবহার করতে পারি না ।

// NOT WORKING:
template<template<class> class STLContainer, class T>
bool contains( STLContainer<T> container, T elt )
{
  return find( container.begin(), container.end(), elt ) != container.end() ;
}

শেষ উত্তরটি উন্নত করার বিষয়ে কোনও মন্তব্য দুর্দান্ত হবে।


দুঃখিত, আমি আসলে মন্তব্যে ব্লক কোডটি লিখতে পারছি না তবে কী হবে template<typename CONTAINER, typename CONTAINEE> bool contains(const CONTAINER& container, const CONTAINEE& needle) { return find(container.begin(), container.end(), needle) != container.end();
ফুলমিওটন

এটি কাজ করছে না, কারণ স্ট্যান্ড :: ভেক্টরকে টেমপ্লেট আর্গুমেন্ট হিসাবে অতিরিক্ত বরাদ্দক প্রয়োজন এবং স্টাড :: সেটটির জন্য বরাদ্দকারী এবং কম টেম্পলেট যুক্তি প্রয়োজন। এই রেখাগুলি কাজ করবে: টেমপ্লেট <টেমপ্লেট <ক্লাস, শ্রেণি> শ্রেণি এসটিএল কনটেইনার, শ্রেণি টি, শ্রেণি এ> বুল রয়েছে (এসটিএল কনটেইনার <টি, এ> ধারক, টি এল্ট) {রিটার্ন ফাইন্ড (ধারক.বেগিন (), ধারক.এন্ড ( ), এল্ট)! = ধারক.end (); } টেমপ্লেট <টেমপ্লেট <ক্লাস, শ্রেণি, শ্রেণি> শ্রেণি এসটিএল কনটেনার, শ্রেণি টি, শ্রেণী এল, শ্রেণি এ> বুল রয়েছে (এসটিএল কনটেইনার <টি, এ, এল> ধারক, টি এল্ট) {রিটার্ন সন্ধান (ধারক.বেগিন (), ধারক .end (), এল্ট)! = ধারক.এন্ড (); }
tgmath

0

// সাধারণ সিনট্যাক্স

       set<int>::iterator ii = find(set1.begin(),set1.end(),"element to be searched");

/ * নীচে কোডে আমি উপাদান 4 ইনট এবং ইনট সেট উপস্থিত থাকলে এটি উপস্থিত কিনা তা চেষ্টা করার চেষ্টা করছি * /

set<int>::iterator ii = find(set1.begin(),set1.end(),4);
 if(ii!=set1.end())
 {
    cout<<"element found";
    set1.erase(ii);// in case you want to erase that element from set.
 }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.