std :: back_inserter for a std :: সেট?


98

আমি অনুমান করি এটি একটি সাধারণ প্রশ্ন। আমাকে এরকম কিছু করতে হবে:

std::set<int> s1, s2;
s1 = getAnExcitingSet();
std::transform(s1.begin(), s1.end(), std::back_inserter(s2), ExcitingUnaryFunctor());

অবশ্যই, std::back_inserterযেহেতু কিছুই নেই কাজ করে না push_backstd::inserterএছাড়াও একটি পুনরুক্তি প্রয়োজন? আমি ব্যবহার std::inserterকরিনি তাই আমি কী করব তা নিশ্চিত নই।

কারো কি কোন ধারণা আছে?


অবশ্যই, আমার অন্য বিকল্পটি হ'ল এর জন্য কোনও ভেক্টর ব্যবহার করা s2এবং তারপরে এটি ঠিক পরে সাজান। সম্ভবত এটি আরও ভাল?

উত্তর:


143

setনেই push_backকারণ কোনও উপাদানের অবস্থানটি সেটের তুলক দ্বারা নির্ধারিত হয়। এটি ব্যবহার std::inserterএবং পাস .begin():

std::set<int> s1, s2;
s1 = getAnExcitingSet();
transform(s1.begin(), s1.end(), 
          std::inserter(s2, s2.begin()), ExcitingUnaryFunctor());

সন্নিবেশ পুনরাবৃত্তির পরে কল করা হবে এটিতে যখন এটির পাঠানো হয় তখন এটি s2.insert(s2.begin(), x)কোথায় xপাঠানো হয়। সেটটি ratorোকানোর জন্য ইঙ্গিত হিসাবে পুনরুক্তি ব্যবহার করে। আপনি হিসাবে ভাল ব্যবহার করতে পারে s2.end()


4
যেহেতু inserter(vec, vec.end())ভেক্টরগুলির জন্যও কাজ করে, কেন কেউ প্রথমে ব্যাক_ইনসেটর ব্যবহার করে?
এনএইচডালি

7
@ এনএইচডি: কারণ ব্যাক_ইনসেটর দ্রুত
marton78

@ মার্টন 7878 তবে কি খুব সামান্য ব্যবধানে কেবল দ্রুত হওয়া উচিত নয়? যখন কোনও উপাদান সরানো না হয় তখন কোনও ভেক্টরের insertপরিবর্তে কল push_backকরা মোটামুটি অভিন্ন (O (1)) হওয়া উচিত।
ফেলিক্স ডমব্যাক

4
@ ফ্যালিক্সডমব্যাক আপনি ঠিক বলেছেন, এটি খুব ধীর হবে না। v.insert(x, v.end())শুরুর দিকে একটি অতিরিক্ত শাখা থাকবে (এটি এন উপাদানগুলির সাথে চলমান কারণে, তবে এখানে এনটি শূন্য)। তবে, inserter1) ব্যবহার করা push_back2 ব্যবহারের চেয়ে পৃথক অভিপ্রায় যোগাযোগ করে ) অস্বাভাবিক এবং পাঠককে থামিয়ে দেয় এবং ভাবেন 3) একটি অকাল হতাশা।
marton78

0

২০১ In সালে একটি "একক যুক্তি inserterপুনরাবৃত্তি" করার প্রস্তাব ছিল । https://isocpp.org/files/papers/p0471r0.html । প্রস্তাবটি অগ্রসর হয়েছে কিনা তা আমি খুঁজে পাইনি। আমি এটা জ্ঞান করে তোলে মনে করি।

আপাতত আপনি এই আচরণটি নির্মাতার কার্যকারিতা সংজ্ঞায়িত করতে পারেন:

template<class Container>
auto sinserter(Container& c){
    using std::end;
    return std::inserter(c, end(c));
}

হিসাবে ব্যবহার:

std::transform(begin(my_vec), end(my_vec), sinserter(my_set), [](auto& e){return e.member;});

এটি কি সমস্ত স্ট্যান্ডার্ড পাত্রে কাজ করার উদ্দেশ্যে? এটি স্ট্যান্ড :: ফরোয়ার্ড_লিস্টে কাজ করে না (সংকলক ত্রুটিটি "ফরওয়ার্ডলিস্টের 'সন্নিবেশ' নামে কোনও সদস্য নেই, এর তাত্ক্ষণিকের ভিতরে insert_iterator::operator=)। এটি করা উচিত?
ডন হ্যাচ

@ দনহ্যাচ, যা কিছু আছে insert(এবং end)। মনে হচ্ছে প্রথম স্থানে forward_listকোনও insertঅপারেশন নেই, কেবলমাত্র insert_after। এবং যদি এটি পরিবর্তন হয় তবে এটি শেষের পরে beোকানো যাবে না, আমি মনে করি। আপনি কি std::listপরিবর্তে ব্যবহার করতে পারবেন না ?
alfC

অবশ্যই, আমার ব্যক্তিগতভাবে স্ট্যান্ড :: ফরোয়ার্ড_লিস্টের কোনও প্রয়োজন নেই। তবে আমি একটি জেনেরিক সম্পর্কে আগ্রহী "আমি কীভাবে একটি ধারককে অন্য কন্টেন্টে কপি করব?" সমস্ত জোড়ের পাত্রে যার জন্য এটি বোঝা যায়। আমার বর্তমান আগ্রহ হ'ল জার্নার কনটেইনার বরাদ্দকারীদের যেমন অনুগ্রহ করে @ হাওয়ার্ডহিন্যান্টের শর্ট_লোক for
ডন হ্যাচ

@ দনহ্যাচ, বিষয়টি হল যে প্রশ্নটির বিভিন্ন রূপ রয়েছে। ("" আমি কীভাবে একটি ধারকটিকে অন্য কন্টেন্টে অনুলিপি করব? ") উদাহরণস্বরূপ, আপনি কি মূল মানগুলি সংরক্ষণ করতে চান, আপনি কী বরাদ্দকে হ্রাস করতে চান ইত্যাদি the সবচেয়ে সহজ ক্ষেত্রে আমার মতের সেরা উত্তরটি হ'ল ব্যবহার করা ধারক দুই iterators লাগে কন্সট্রাকটর (অধিকাংশ পাত্রে যে নিতে পারেন)। NewContaner new_container(old_other_container.begin(), old_other_container.end())
alfC

4
হ্যাঁ, std :: সেটটি সিক্যুয়াল কনটেনার নয়, এবং এটি দুর্দান্ত :-) existing_list = std::list(c.begin(), c.end(), existing_list.get_allocator()) খুব সুন্দর, আমি মনে করি এটি আমার উত্তর। চিয়ার্স!
ডন হ্যাচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.