আমি কীভাবে তাদের "সি" + এর সাথে "যদি" শর্তটি দিয়ে "লুপ" এড়াতে পারি?


111

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

for(int i=0; i<myCollection.size(); i++)
{
     if (myCollection[i] == SOMETHING)
     {
           DoStuff();
     }
}

ক্রিয়ামূলক ভাষার সাহায্যে আমি সংগ্রহটি অন্য সংগ্রহের (সহজেই) কমিয়ে সমস্যার সমাধান করতে পারি এবং তারপরে আমার হ্রাস করা সেটটিতে সমস্ত ক্রিয়াকলাপ সম্পাদন করতে পারি। সিউডোকোডে:

newCollection <- myCollection where <x=true
map DoStuff newCollection

এবং অন্যান্য সি ভেরিয়েন্টে, সি # এর মতো আমি যেখানে ক্লজ পছন্দ করতে পারে তার সাথে হ্রাস করতে পারি

foreach (var x in myCollection.Where(c=> c == SOMETHING)) 
{
   DoStuff();
}

বা আরও ভাল (কমপক্ষে আমার চোখে)

myCollection.Where(c=>c == Something).ToList().ForEach(d=> DoStuff(d));

স্বীকার করা যায়, আমি প্রচুর দৃষ্টান্ত মিশ্রণ এবং বিষয়গত / মতামত ভিত্তিক শৈলী করছি, কিন্তু আমি সাহায্য করতে পারি না কিন্তু অনুভব করতে পারি না যে আমি সত্যিই মৌলিক কিছু অনুভব করছি যা আমাকে সি ++ দিয়ে এই পছন্দসই কৌশলটি ব্যবহার করতে দেয়। কেউ আমাকে আলোকিত করতে পারে?


7
সি ++ স্ট্যান্ডার্ড লাইব্রেরির কার্যকারিতা থেকে আপনি চেষ্টা করতে পারেন std::copy_if, তবে নির্বাচনগুলি অলস নয়
সহস্রাব্দ

14
আপনি পরিসীমা- v3 এ আগ্রহী হতে পারেন । এটি টিএস হিসাবে সি ++ এ আসা উচিত এবং ভবিষ্যতে প্রকাশে আশা করা যায় যে এটি মানকযুক্ত।
নাথান অলিভার

12
আমি উল্লেখ করার প্রয়োজনটি অনুভব করি যে আপনি যেটির উল্লেখ করেছেন তার ifভিতরে forকেবলমাত্র অন্য উদাহরণগুলির সাথে সামঞ্জস্যপূর্ণ নয় বরং অনেকগুলি ক্ষেত্রে সম্ভবত দ্রুতও হবে। এছাড়াও কারও পক্ষে যারা কার্যকরী শৈলী পছন্দ করে বলে দাবি করেন, আপনি যা প্রচার করছেন তা কার্যকরী প্রোগ্রামিংয়ের বিশুদ্ধতার প্রিয়তম ধারণার বিরুদ্ধে যাচ্ছেন বলে DoStuffস্পষ্টভাবে পার্শ্বপ্রতিক্রিয়া রয়েছে।
ফারাপ

60
আমি কখনই বুঝতে পারি নি কেন লোকেরা সমস্ত যুক্তিকে একক লাইনের সাথে সংযুক্ত করে এটি কোনওরকম আরও ভাল বা আরও বেশি পঠনযোগ্য দেখায়। তোমার সি ++ স্নিপেট খুব শীর্ষে দ্বারা পর্যন্ত আপনার সম্ভাবনার সব আউট আমার কাছে সবচেয়ে পাঠযোগ্য। এবং যেহেতু দক্ষতা পরিবর্তন করা হবে না, আমি বুঝতে পারি না আপনি কেন এটি লিখতে পছন্দ করেন না, যদি না আপনি মুছে ফেলা কোডের লাইন সংখ্যার দ্বারা প্রদান করা হয়।
কোডি গ্রে

10
@ কোডি গ্রেড একমত: এটি 'সিনট্যাকটিক চিনি মাত্র। এবং প্রশ্নের শিরোনাম বিভ্রান্তিমূলক, কারণ এটি শাখা প্রশাখা এড়ানো এবং বিমূর্ততার আওতায় এটি আড়াল করা একেবারেই আলাদা ।
edmz

উত্তর:


99

আইএমএইচও এটি আরও সোজা এগিয়ে এবং এর ভিতরে যদি লুপের জন্য ব্যবহার করতে আরও পড়তে পারা যায়। তবে এটি যদি আপনার জন্য বিরক্তিকর হয় তবে আপনি for_each_ifনীচের মত ব্যবহার করতে পারেন :

template<typename Iter, typename Pred, typename Op> 
void for_each_if(Iter first, Iter last, Pred p, Op op) {
  while(first != last) {
    if (p(*first)) op(*first);
    ++first;
  }
}

ব্যবহারের ক্ষেত্রে:

std::vector<int> v {10, 2, 10, 3};
for_each_if(v.begin(), v.end(), [](int i){ return i > 5; }, [](int &i){ ++i; });

সরাসরি নমুনা


10
এটি ব্যতীত চালাক। আমি এটিও সম্মত করব যে এটি সরাসরি এগিয়ে নেই এবং আমি সম্ভবত শর্তগুলি ব্যবহার করব যখন প্রোগ্রামিং সি ++ যা অন্যরা গ্রাস করে। তবে আমার নিজের ব্যক্তিগত ব্যবহারের জন্য এটি ঠিক আমার প্রয়োজন! :)
ডার্কেনর

14
@ ডিফল্ট কনটেইনারগুলির পরিবর্তে পুনরাবৃত্তকারী জুড়িগুলি আরও নমনীয় এবং আইডোমেটিক সি ++ উভয়ই।
বি

8
@ স্লাভা, সাধারণ পরিসীমা অ্যালগরিদমের সংখ্যা হ্রাস করবে না। উদাহরণস্বরূপ, আপনার এখনও প্রয়োজন find_ifএবং findতারা পুনরায় বা পুনরুক্তিগুলির জোড়াগুলির উপর কাজ করে কিনা। (কয়েকটি ব্যতিক্রম যেমন আছে for_eachএবং for_each_n)। পথ যে হাঁচি জন্য নতুন algos লেখা এড়াতে বিদ্যমান algos সঙ্গে বিভিন্ন অপারেশন ব্যবহার করার পরিবর্তে যেমন হয় for_each_ifcallable প্রেরণ মধ্যে শর্ত এম্বেড for_each, যেমনfor_each(first, last, [&](auto& x) { if (cond(x)) f(x); });
জনাথন Wakely

9
আমাকে প্রথম বাক্যটির সাথে একমত হতে হবে: আদর্শ সমাধান যদি এর সাথে সমাধান করা হয় তবে এটি কাজ করা আরও বেশি পঠনযোগ্য এবং সহজ। আমি মনে করি লাম্বদা সিনট্যাক্স এবং কোনও সাধারণ লুপটি পরিচালনা করতে অন্য কোথাও সংজ্ঞায়িত টেম্পলেটটির ব্যবহার জ্বালাতন করতে পারে বা সম্ভবত অন্য দেবগুলিকে বিভ্রান্ত করবে। আপনি লোকালয় এবং পারফরম্যান্সের জন্য আত্মত্যাগ করছেন ... কি? এক লাইনে কিছু লিখতে পারছেন?
ব্যবহারকারী1354557

45
কাশি @ ডার্কেনর, সাধারণত " ব্যতিক্রমী চতুর" প্রোগ্রামিং এড়ানো উচিত কারণ এটি আপনার ভবিষ্যতের স্বাসহ অন্য সকলের বকবিকে বিরক্ত করে।
রায়ান

48

বুস্ট এমন রেঞ্জ সরবরাহ করে যা ডাব্লু / রেঞ্জ-ভিত্তিক ব্যবহার করা যায়। রেঞ্জ যে তারা অন্তর্নিহিত ডাটা স্ট্রাকচার কপি করবেন না, তারা নিছক একটি 'ভিউ' প্রদান সুবিধা আছে (যে begin(), end()কাজ করার জন্য এবং operator++(), operator==()পুনরুক্তিকারীর জন্য)। এটি আপনার আগ্রহের বিষয় হতে পারে: http://www.boost.org/libs/range/doc/html/range/references/adaptors/references/filtered.html

#include <boost/range/adaptor/filtered.hpp>
#include <iostream>
#include <vector>

struct is_even
{
    bool operator()( int x ) const { return x % 2 == 0; }
};

int main(int argc, const char* argv[])
{
    using namespace boost::adaptors;

    std::vector<int> myCollection{1,2,3,4,5,6,7,8,9};

    for( int i: myCollection | filtered( is_even() ) )
    {
        std::cout << i;
    }
}

1
আমি পরিবর্তে ওপিএস উদাহরণটি ব্যবহার করার পরামর্শ দিতে পারি, অর্থাত্ is_even=> condition, input=> myCollectionইত্যাদি
ডিফল্ট

এটি একটি চমত্কার উত্তর এবং অবশ্যই আমি যা করতে চাই। অলস / স্থগিত মৃত্যুদন্ড কার্যকর করার জন্য কেউ যদি কোনও মানক আনুগত্যের উপায় না নিয়ে আসে তবে আমি গ্রহণযোগ্যতা অবলম্বন করতে যাচ্ছি। সম্মত।
ডার্কেনর

5
@ ডারকেনর: যদি বুস্ট আপনার কাছে সমস্যা হয় (যেমন, কোম্পানির নীতি এবং পরিচালক প্রজ্ঞার কারণে আপনি এটি ব্যবহার নিষিদ্ধ করেছেন), আমি আপনার filtered()জন্য একটি সরল সংজ্ঞা দিতে পারি - এটি বলেছে, এটি ব্যবহার করা ভাল better কিছু অ্যাড-হক কোডের চেয়ে একটি সমর্থিত লাইব।
লোরো

একদম একমত তোমার সাথে. আমি এটি গ্রহণ করেছি কারণ স্ট্যান্ডার্ড-কমপ্লায়েন্ট উপায়টি প্রথম এসেছিল কারণ প্রশ্নটি সি ++ নিজেই তৈরি হয়েছিল, বুস্ট লাইব্রেরি নয়। তবে এটি সত্যিই দুর্দান্ত। এছাড়াও - হ্যাঁ, আমি দুঃখের সাথে অনেক জায়গায় এমন জায়গায় কাজ করেছি যা
বেস্ট কাজের

@ লাইক্লেজেট:? ।
লোরো

44

নতুন অ্যালগরিদম তৈরির পরিবর্তে, যেমন গ্রহণযোগ্য উত্তর দেয়, আপনি শর্তটি প্রয়োগ করে এমন একটি ফাংশন সহ একটি বিদ্যমান ব্যবহার করতে পারেন:

std::for_each(first, last, [](auto&& x){ if (cond(x)) { ... } });

অথবা আপনি যদি সত্যিই একটি নতুন অ্যালগরিদম চান তবে কমপক্ষে for_eachপুনরাবৃত্তি যুক্তিটিকে নকল করার পরিবর্তে পুনরায় ব্যবহার করুন :

template<typename Iter, typename Pred, typename Op> 
  void
  for_each_if(Iter first, Iter last, Pred p, Op op) {
    std::for_each(first, last, [&](auto& x) { if (p(x)) op(x); });
  }

স্ট্যান্ডার্ড লাইব্রেরি ব্যবহারের জন্য আরও অনেক ভাল এবং পরিষ্কার।
বেনামে

4
কারণ std::for-each(first, last, [&](auto& x) {if (p(x)) op(x); });সম্পূর্ণ সহজ তুলনায় for (Iter x = first; x != last; x++) if (p(x)) op(x);}?
ব্যবহারকারী 253751

2
@ মিমিবিস স্ট্যান্ডার্ড লাইব্রেরিটির পুনরায় ব্যবহারের অন্যান্য সুবিধা রয়েছে যেমন পুনরুদ্ধারের বৈধতা যাচাইকরণ, বা (সি ++ 17 তে) আরও একটি যুক্তি যুক্ত করে সমান্তরাল করা আরও std::for_each(std::execution::par, first, last, ...);সহজ : এই জিনিসগুলিকে একটি হাতের লিখিত লুপে যুক্ত করা কত সহজ?
জোনাথন ওয়াকলি

1
#pragma omp এর সমান্তরাল
মার্ক কে কোয়ান

2
@ মার্ক দুঃখিত, আপনার উত্স কোড বা বিল্ড চেইনের কিছু এলোমেলো ছোঁয়া তৈরি করেছে যে বিরক্তিকরভাবে ভঙ্গুর সমান্তরাল অ-মানক সংকলক এক্সটেনশন কোনও ডায়াগনস্টিক ছাড়াই শূন্য পারফরম্যান্স উত্সাহ জেনার করে।
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

21

এড়িয়ে যাওয়ার ধারণা

for(...)
    if(...)

অ্যান্টিপ্যাটার্ন হিসাবে নির্মাণগুলি খুব বিস্তৃত।

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

for(...)
    if(...)
        do_process(...);

এর থেকে বেশি পছন্দনীয়

for(...)
    maybe_process(...);

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

for(int i = 0; i < size; ++i)
    if(i == 5)

এটির চরম এবং সুস্পষ্ট উদাহরণ। আরও সূক্ষ্ম, এবং এইভাবে আরও সাধারণ, কারখানার মতো

for(creator &c : creators)
    if(c.name == requested_name)
    {
        unique_ptr<object> obj = c.create_object();
        obj.owner = this;
        return std::move(obj);
    }

এটি পড়া শক্ত, কারণ এটি স্পষ্ট নয় যে বডি কোডটি একবারে কার্যকর করা হবে। এই ক্ষেত্রে, চেহারা পৃথক করা ভাল হবে:

creator &lookup(string const &requested_name)
{
    for(creator &c : creators)
        if(c.name == requested_name)
            return c;
}

creator &c = lookup(requested_name);
unique_ptr obj = c.create_object();

এ এর ifমধ্যে একটি এখনও রয়েছে for, তবে প্রেক্ষাপট থেকে এটি স্পষ্ট হয়ে ওঠে যে এটি কী করে, যদি না অনুসন্ধান পরিবর্তন হয় (উদাহরণস্বরূপ এ map) অবধি এই কোডটি পরিবর্তন করার দরকার নেই , এবং এটি অবিলম্বে পরিষ্কার হয়ে গেছে যে create_object()কেবল একবার বলা হয়, কারণ এটি একটি লুপ ভিতরে না।


আমি এটি একটি বিবেচ্য এবং ভারসাম্য ওভারভিউ হিসাবে পছন্দ করি, যদিও এটি যদি এক অর্থে উত্থাপিত প্রশ্নের উত্তর দিতে অস্বীকার করে তবে। আমি দেখতে পেলাম যে- for( range ){ if( condition ){ action } }স্টাইলটি একবারে জিনিসগুলি একসাথে পড়া সহজ করে তোলে এবং কেবলমাত্র মৌলিক ভাষা নির্মানের জ্ঞান ব্যবহার করে।
পিজেট্রাইল

@ পিজেট্রাইল, যেভাবে প্রশ্নটি উত্থাপিত হয়েছিল তা আমাকে স্মরণ করিয়ে দিয়েছে রেমন্ড চেনের অ্যান্টিপ্যাটার্ন-এর বিরুদ্ধে অভিজাতদের বিরুদ্ধে , যা কার্গো-আটকানো হয়েছে এবং একরকম পরম হয়ে উঠেছে। আমি সম্পূর্ণরূপে সম্মত হই যে for(...) if(...) { ... }প্রায়শই সেরা পছন্দ (সেই কারণেই আমি ক্রিয়াটি সাব্রোটিনে বিভক্ত করার জন্য সুপারিশটি যোগ্য করেছিলাম)।
সাইমন রিখটার

1
লিঙ্কটির জন্য ধন্যবাদ, যা আমার জন্য বিষয়গুলি স্পষ্ট করেছে: " for-if " নামটি বিভ্রান্তিকর, এবং " for-all-if-one " বা " অনুসন্ধান-এড়ানো " এর মতো কিছু হওয়া উচিত । এটি ২০০২ সালে উইকিপিডিয়া দ্বারা যেভাবে অ্যাবস্ট্রাকশন বিপরীতকে বর্ণনা করা হয়েছিল তা মনে করিয়ে দেয় যে কেউ যখন " জটিল ( উপরে )গুলির উপরে সাধারণ কাঠামো তৈরি করে" - যতক্ষণ না আমি এটি পুনরায় লিখি! প্রকৃতপক্ষে আমি এমনকি লুকিং-প্রক্রিয়া-প্রস্থান ফর্মটি ঠিক করার জন্য তাড়াহুড়ো করব না যদি এটি কেবলমাত্র স্থান অনুসন্ধান ছিল। for(…)if(…)…
পিজেট্রাইল

17

এখানে একটি দ্রুত অপেক্ষাকৃত ন্যূনতম filterফাংশন।

এটি একটি শিকারী লাগে। এটি একটি ফাংশন অবজেক্ট প্রদান করে যা পুনরাবৃত্ত হয়।

এটি একটি পুনরুক্তি করে যা একটি for(:)লুপে ব্যবহার করা যায় ।

template<class It>
struct range_t {
  It b, e;
  It begin() const { return b; }
  It end() const { return e; }
  bool empty() const { return begin()==end(); }
};
template<class It>
range_t<It> range( It b, It e ) { return {std::move(b), std::move(e)}; }

template<class It, class F>
struct filter_helper:range_t<It> {
  F f;
  void advance() {
    while(true) {
      (range_t<It>&)*this = range( std::next(this->begin()), this->end() );
      if (this->empty())
        return;
      if (f(*this->begin()))
        return;
    }
  }
  filter_helper(range_t<It> r, F fin):
    range_t<It>(r), f(std::move(fin))
  {
      while(true)
      {
          if (this->empty()) return;
          if (f(*this->begin())) return;
          (range_t<It>&)*this = range( std::next(this->begin()), this->end() );
      }
  }
};

template<class It, class F>
struct filter_psuedo_iterator {
  using iterator_category=std::input_iterator_tag;
  filter_helper<It, F>* helper = nullptr;
  bool m_is_end = true;
  bool is_end() const {
    return m_is_end || !helper || helper->empty();
  }

  void operator++() {
    helper->advance();
  }
  typename std::iterator_traits<It>::reference
  operator*() const {
    return *(helper->begin());
  }
  It base() const {
      if (!helper) return {};
      if (is_end()) return helper->end();
      return helper->begin();
  }
  friend bool operator==(filter_psuedo_iterator const& lhs, filter_psuedo_iterator const& rhs) {
    if (lhs.is_end() && rhs.is_end()) return true;
    if (lhs.is_end() || rhs.is_end()) return false;
    return lhs.helper->begin() == rhs.helper->begin();
  }
  friend bool operator!=(filter_psuedo_iterator const& lhs, filter_psuedo_iterator const& rhs) {
    return !(lhs==rhs);
  }
};
template<class It, class F>
struct filter_range:
  private filter_helper<It, F>,
  range_t<filter_psuedo_iterator<It, F>>
{
  using helper=filter_helper<It, F>;
  using range=range_t<filter_psuedo_iterator<It, F>>;

  using range::begin; using range::end; using range::empty;

  filter_range( range_t<It> r, F f ):
    helper{{r}, std::forward<F>(f)},
    range{ {this, false}, {this, true} }
  {}
};

template<class F>
auto filter( F&& f ) {
    return [f=std::forward<F>(f)](auto&& r)
    {
        using std::begin; using std::end;
        using iterator = decltype(begin(r));
        return filter_range<iterator, std::decay_t<decltype(f)>>{
            range(begin(r), end(r)), f
        };
    };
};

শর্ট কাট নিলাম। একটি বাস্তব গ্রন্থাগারকে সত্যিকারের for(:)পুনরাবৃত্তি করা উচিত, আমি যে-যোগ্য সিউডো-ফ্যাসাডকে করেছিলাম তা নয়।

ব্যবহারের স্থানে, এটি দেখতে এটির মতো দেখাচ্ছে:

int main()
{
  std::vector<int> test = {1,2,3,4,5};
  for( auto i: filter([](auto x){return x%2;})( test ) )
    std::cout << i << '\n';
}

যা বেশ সুন্দর, এবং প্রিন্ট

1
3
5

সরাসরি উদাহরণ

রেঞ্জেস 3 নামক সি ++ তে প্রস্তাবিত সংযোজন রয়েছে যা এই ধরণের জিনিস এবং আরও অনেক কিছু করে। boostএছাড়াও ফিল্টার ব্যাপ্তি / পুনরাবৃত্তি উপলব্ধ। বুস্টের এমন সহায়কও রয়েছে যা উপরের লেখাকে আরও ছোট করে তোলে।


15

একটি স্টাইল যা উল্লেখ করার জন্য যথেষ্ট ব্যবহৃত হয়, তবে এখনও উল্লেখ করা হয়নি, তা হ'ল:

for(int i=0; i<myCollection.size(); i++) {
  if (myCollection[i] != SOMETHING)
    continue;

  DoStuff();
}

সুবিধাদি:

  • DoStuff();যখন শর্ত জটিলতা বৃদ্ধি পায় তখন ইন্ডেন্টেশন স্তর পরিবর্তন করে না । যৌক্তিকভাবে, লুপটির DoStuff();শীর্ষ স্তরের হওয়া উচিত for, এবং এটি।
  • অবিলম্বে এটা পরিষ্কার করে তোলে উপর লুপ iterates SOMETHINGসংগ্রহ এস, ক্লোজিং পর আর কিছুই নেই যাচাই করার জন্য পাঠক প্রয়োজন ছাড়া }এর ifব্লক।
  • কোনও লাইব্রেরি বা সহায়ক ম্যাক্রো বা ফাংশন প্রয়োজন হয় না।

অসুবিধা:

  • continueঅন্যান্য ফ্লো কন্ট্রোল স্টেটমেন্টগুলির মতো, এমনভাবে ব্যবহার করা হয় যা কঠোরভাবে অনুসরণ করা কোডের দিকে পরিচালিত করে যাতে কিছু লোক তাদের যে কোনও ব্যবহারের বিরোধিতা করে: কোডিংয়ের একটি বৈধ শৈলী রয়েছে যে এটি অনুসরণ করে যে কিছু এড়ানো হয় continue, যা breakব্যতীত অন্যকে এড়ানো হয় একটি মধ্যে switch, এটি returnএকটি ফাংশন শেষে ছাড়া অন্য এড়ানো ।

3
আমি যুক্তি দিয়ে বলব যে একটি forলুপ যা বহু লাইনে চলে, "দ্বি-লাইন" যদি না হয় তবে চালিয়ে যাও "অনেক বেশি পরিষ্কার, যৌক্তিক এবং পঠনযোগ্য। তাত্ক্ষণিকভাবে বলা, "এটি ছেড়ে যান" forবিবৃতিটি ভালভাবে পড়ার পরে এবং যেমনটি আপনি বলেছেন, লুপের বাকী কার্যকরী দিকগুলি ইন্ডেন্ট করে না। যদি continueআরও নিচে থাকে তবে কিছু স্পষ্টতাই বলি দেওয়া হয় (অর্থাত্ ifবিবৃতি দেওয়ার আগে কিছু অপারেশন সর্বদা করা হবে )।
বেনামে

11
for(auto const &x: myCollection) if(x == something) doStuff();

দেখতে অনেকটা সি ++ এর মতো - forআমার কাছে নির্দিষ্ট বোঝা। তোমাকে?


আমি মনে করি না অটো কীওয়ার্ডটি সি ++ 11 এর আগে উপস্থিত ছিল তাই আমি এটি বলব না যে এটি খুব ধ্রুপদী সি ++। আমি যদি এখানে মন্তব্যে একটি প্রশ্ন জিজ্ঞাসা করতে পারি, "অটো কনস্ট" সংকলককে কি এটি বলবে যে এটি সমস্ত উপাদানগুলি যেমনটি চায় তেমনভাবে সাজিয়ে তুলতে পারে? সম্ভবত যদি কম্পাইলারের পক্ষে শাখা প্রশাখি এড়ানোর পরিকল্পনা করা সহজ হয় তবে এটি ঘটতে পারে।
ম্যাথ্রেডলার

1
@ ম্যাথ্রেডলার যত তাড়াতাড়ি লোকেরা "ধ্রুপদী সি ++" সম্পর্কে চিন্তাভাবনা করা বন্ধ করবেন তত ভাল। সি ++ 11 ভাষাটির জন্য একটি ম্যাক্রোভোলিউশনারি ইভেন্ট ছিল এবং এটি 5 বছরের পুরানো: এটি আমাদের পক্ষে সর্বনিম্ন চেষ্টা করা উচিত । যাইহোক, ওপি ট্যাগ করেছে এবং সি ++ 14 (আরও ভাল!)। না, auto constপুনরাবৃত্তি আদেশে যা আছে তা নিয়ে কোনও প্রভাব নেই। আপনি সীমাকৃত ভিত্তিক খোঁজা তাহলে for, আপনি যে এটি মূলত থেকে একটি প্রমিত লুপ আছে দেখতে পাবেন begin()করার end()অন্তর্নিহিত dereferencing সঙ্গে। কনটেইনারটি পুনরাবৃত্তি হওয়ার আদেশের গ্যারান্টি (যদি থাকে তবে) ভঙ্গ করতে পারে এমন কোনও উপায় নেই; এটি পৃথিবীর মুখ থেকে উপহাস করা হত
আন্ডারস্কোর_১

1
@ ম্যাথ্রেডলার, আসলে এটি ছিল, এর ঠিক অন্যরকম অর্থ ছিল। যা উপস্থিত ছিল না তা হ'ল ... এবং অন্য কোনও স্বতন্ত্র সি ++ 11 বৈশিষ্ট্য। আমি এখানে যা বোঝাতে চেয়েছি তা হ'ল রেঞ্জ-ফোরস, std::futureএস, std::functionএস, এমনকি সেই বেনামে বন্ধ হওয়াগুলি সিনট্যাক্সে খুব ভাল সি ++ ইশ; প্রত্যেক ভাষার নিজস্ব আলাদা আলাদা পার্থক্য থাকে এবং নতুন বৈশিষ্ট্য অন্তর্ভুক্ত করার সময় এটি তাদেরকে পুরানো সুপরিচিত সিনট্যাক্সের নকল করার চেষ্টা করে।
বাইপেল

@ আসনস্কোর_ডি, কোনও সংকলককে কোনও রূপান্তর সম্পাদন করার অনুমতি দেওয়া হয়েছে যদি শর্ত মেনে চলা হয়, তাই না?
বাইপেল

1
হুম, এবং এর দ্বারা সম্ভবত কী বোঝানো যেতে পারে?
বাইপেল

7

যদি ডস্ট স্টাফ () ভবিষ্যতে কোনওভাবেই আমার উপর নির্ভরশীল তবে আমি এই গ্যারান্টিযুক্ত শাখাবিহীন বিট-মাস্কিং ভেরিয়েন্টটি প্রস্তাব করব।

unsigned int times = 0;
const int kSize = sizeof(unsigned int)*8;
for(int i = 0; i < myCollection.size()/kSize; i++){
  unsigned int mask = 0;
  for (int j = 0; j<kSize; j++){
    mask |= (myCollection[i*kSize+j]==SOMETHING) << j;
  }
  times+=popcount(mask);
}

for(int i=0;i<times;i++)
   DoStuff();

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

for(int i = 0; i < myCollection.size(); i++)
  times += (myCollection[i]==SOMETHING);

এর পরে a

for(int i=0;i<times;i++)
   DoStuff();

6

এছাড়াও, আপনি যদি সংগ্রহটি পুনরায় অর্ডার করার বিষয়ে চিন্তা না করেন তবে std :: পার্টিশনটি সস্তা।

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

void DoStuff(int i)
{
    std::cout << i << '\n';
}

int main()
{
    using namespace std::placeholders;

    std::vector<int> v {1, 2, 5, 0, 9, 5, 5};
    const int SOMETHING = 5;

    std::for_each(v.begin(),
                  std::partition(v.begin(), v.end(),
                                 std::bind(std::equal_to<int> {}, _1, SOMETHING)), // some condition
                  DoStuff); // action
}

তবে std::partitionধারকটি পুনরায় অর্ডার করে।
celtschk

5

আমি উপরের সমাধানগুলির জটিলতায় বিস্মিত হই। আমি একটি সহজ পরামর্শ দিতে যাচ্ছিলাম #define foreach(a,b,c,d) for(a; b; c)if(d)তবে এর কয়েকটি সুস্পষ্ট ঘাটতি রয়েছে, উদাহরণস্বরূপ, আপনাকে আপনার লুপে অর্ধপরিমাণের পরিবর্তে কমা ব্যবহার করতে হবে এবং আপনি aবা কমাতে অপারেটরটি ব্যবহার করতে পারবেন না c

#include <list>
#include <iostream>

using namespace std; 

#define foreach(a,b,c,d) for(a; b; c)if(d)

int main(){
  list<int> a;

  for(int i=0; i<10; i++)
    a.push_back(i);

  for(auto i=a.begin(); i!=a.end(); i++)
    if((*i)&1)
      cout << *i << ' ';
  cout << endl;

  foreach(auto i=a.begin(), i!=a.end(), i++, (*i)&1)
    cout << *i << ' ';
  cout << endl;

  return 0;
}

3
কিছু উত্তরের জটিলতা কেবলমাত্র উচ্চ কারণ তারা প্রথমে পুনরায় ব্যবহারযোগ্য জেনেরিক পদ্ধতি প্রদর্শন করে (যা আপনি কেবল একবারই করতে পারেন) এবং তারপরে এটি ব্যবহার করুন। কার্যকরী নয় যদি আপনি এক আপনার পুরো অ্যাপ্লিকেশনে একটি যদি শর্ত লুপ কিন্তু খুব কার্যকর যদি এটি একটি হাজার হাজার গুণ ঘটবে।
gnasher729

1
বেশিরভাগ পরামর্শের মতো, এটি পরিসীমা এবং নির্বাচনের শর্ত সনাক্ত করতে আরও শক্ত, সহজ নয়। এবং ম্যাক্রোর ব্যবহার কখন (এবং কতবার) এক্সপ্রেশনগুলি মূল্যায়ন করা হয় তা সম্পর্কে অনিশ্চয়তা বাড়িয়ে তোলে, এমনকি এখানে কোনও আশ্চর্য না থাকলেও।
পিজেট্রাইল

2

আই: এস গুরুত্বপূর্ণ হ'ল ক্ষেত্রে আর একটি সমাধান। এটি একটি এমন তালিকা তৈরি করে যা ডু স্টাফ () এর জন্য কল করতে হবে এমন সূচীতে পূর্ণ হয়। আবারও মূল বিষয় হ'ল ব্রাঞ্চিং এড়ানো এবং পাইপলাইনযোগ্য গাণিতিক ব্যয়ের জন্য এটি বাণিজ্য করা।

int buffer[someSafeSize];
int cnt = 0; // counter to keep track where we are in list.
for( int i = 0; i < container.size(); i++ ){
   int lDecision = (container[i] == SOMETHING);
   buffer[cnt] = lDecision*i + (1-lDecision)*buffer[cnt];
   cnt += lDecision;
}

for( int i=0; i<cnt; i++ )
   doStuff(buffer[i]); // now we could pass the index or a pointer as an argument.

"ম্যাজিকাল" লাইনটি বাফার লোডিং লাইন যা গাণিতিকভাবে ওয়েথার গণনা করে মান রাখতে এবং অবস্থানে থাকতে বা অবস্থান গণনা করতে এবং মান যোগ করতে। সুতরাং আমরা কিছু যুক্তি এবং পাটিগণিত এবং সম্ভবত কিছু ক্যাশে হিটগুলির জন্য একটি সম্ভাব্য শাখা বাণিজ্য করি। একটি সাধারণ দৃশ্য যখন এটি কার্যকর হবে তা যদি ডস স্টাফ () খুব কম পরিমাণে পাইপলাইনেবল গণনা করে এবং কলগুলির মধ্যে যে কোনও শাখা সেই পাইপলাইনগুলিকে বাধা দিতে পারে।

তারপরে কেবল বাফারের উপর দিয়ে লুপ করুন এবং সিএনটি না পৌঁছানো পর্যন্ত doStuff () চালান। এবার আমাদের কাছে বর্তমান আমি বাফারে সঞ্চিত করব যাতে আমাদের এটির প্রয়োজনে আমরা এটি ডু স্টাফ () এর কলটিতে ব্যবহার করতে পারি।


1

একটি আপনার কোডের প্যাটার্নটিকে কোনও ব্যাপ্তির কোনও উপসেটে কিছু ফাংশন প্রয়োগ করার মতো বর্ণনা করতে পারে বা অন্য কথায়: পুরো ব্যাপ্তিতে ফিল্টার প্রয়োগের ফলাফলটিতে এটি প্রয়োগ করে।

এটি এরিক নেবিলারের রেঞ্জ-ভি 3 লাইব্রেরির সাথে সবচেয়ে সোজা পদ্ধতিতে অর্জনযোগ্য ; যদিও এটি কিছুটা চোখের জলছানা, কারণ আপনি সূচকগুলি নিয়ে কাজ করতে চান:

using namespace ranges;
auto mycollection_has_something = 
    [&](std::size_t i) { return myCollection[i] == SOMETHING };
auto filtered_view = 
    views::iota(std::size_t{0}, myCollection.size()) | 
    views::filter(mycollection_has_something);
for (auto i : filtered_view) { DoStuff(); }

তবে আপনি যদি সূচকগুলি পূর্বে রাখতে চান তবে আপনি পাবেন:

auto is_something = [&SOMETHING](const decltype(SOMETHING)& x) { return x == SOMETHING };
auto filtered_collection = myCollection | views::filter(is_something);
for (const auto& x : filtered_collection) { DoStuff(); }

যা ভাল আইএমএইচও।

পিএস - রেঞ্জ লাইব্রেরি বেশিরভাগ সি ++ 20 এ সি ++ স্ট্যান্ডার্ডে চলেছে।


0

আমি কেবল মাইক অ্যাক্টনের কথা উল্লেখ করব, তিনি অবশ্যই বলবেন:

যদি তা করতে হয় তবে আপনার ডেটা নিয়ে সমস্যা আছে। আপনার তথ্য বাছাই করুন!

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