আপনি যদি শুরু থেকে শেষের দিকে পুনরুক্তি করার সময় মানচিত্রের উপাদানটিতে মুছুন () কে কল করেন?


133

নিম্নলিখিত কোডে আমি একটি মানচিত্রের মধ্য দিয়ে লুপ করছি এবং কোনও উপাদান মোছার দরকার আছে কিনা তা পরীক্ষা করে দেখি। উপাদানটি মুছে ফেলা এবং পুনরাবৃত্তি করা কি নিরাপদ বা আমার অন্য পাত্রে কীগুলি সংগ্রহ করতে এবং মুছে ফেলার জন্য দ্বিতীয় লুপটি করতে হবে ()?

map<string, SerialdMsg::SerialFunction_t>::iterator pm_it;
for (pm_it = port_map.begin(); pm_it != port_map.end(); pm_it++)
{
    if (pm_it->second == delete_this_id) {
        port_map.erase(pm_it->first);
    }
}

আপডেট: অবশ্যই, আমি তখন এই প্রশ্নটি পড়েছিলাম যা আমি মনে করি না যে এটি সম্পর্কিত হতে পারে তবে আমার প্রশ্নের উত্তর দেয়।


দয়া std::remove_ifকরে সেই প্রশ্নে নোট করুনstd:map
সকেটপায়ার এর

উত্তর:


183

সি ++ 11

এটি সি ++ 11 এ স্থির করা হয়েছে (বা মুছে ফেলা হয়েছে / সমস্ত ধারক প্রকারের সাথে সামঞ্জস্যপূর্ণ করা হয়েছে)।
মোছার পদ্ধতিটি এখন পরবর্তী পুনরাবৃত্তিকে প্রদান করে।

auto pm_it = port_map.begin();
while(pm_it != port_map.end())
{
    if (pm_it->second == delete_this_id)
    {
        pm_it = port_map.erase(pm_it);
    }
    else
    {
        ++pm_it;
    }
}

সি ++ 03

মানচিত্রে উপাদানগুলি মুছে ফেলা কোনও পুনরাবৃত্তকারীকে অবৈধ করে না।
(মুছে ফেলা উপাদানটিতে পুনরাবৃত্তকারীদের বাদে)

আসলে সন্নিবেশ করা বা মোছা পুনরুক্তিকারীদের কোনওটিকেই অবৈধ করে না:

এই উত্তরটিও দেখুন:
মার্ক রান্সম টেকনিক

তবে আপনার কোডটি আপডেট করার দরকার নেই:
আপনার কোডে মুছে ফেলার পরে পিএম_আইটি বাড়িয়েছেন। এই মুহুর্তে এটি খুব দেরি হয়ে গেছে এবং ইতিমধ্যে অবৈধ।

map<string, SerialdMsg::SerialFunction_t>::iterator pm_it = port_map.begin();
while(pm_it != port_map.end())
{
    if (pm_it->second == delete_this_id)
    {
        port_map.erase(pm_it++);  // Use iterator.
                                  // Note the post increment.
                                  // Increments the iterator but returns the
                                  // original value for use by erase 
    }
    else
    {
        ++pm_it;           // Can use pre-increment in this case
                           // To make sure you have the efficient version
    }
}

পোস্টফিক্স এক্সপ্রেশনটিতে বর্ধনের মূল্যায়ন করার ক্রমটি pm_it++কার্য সম্পাদনের আগেই কার্যকর করার গ্যারান্টিযুক্ত?
ডেভিড রদ্রিগেজ - ড্রিবিস

4
@ ডেভিড রডগ্রিগজ - ড্রিবিস: হ্যাঁ। মানটি গ্যারান্টি দেয় যে ফাংশনটি বলার আগে সমস্ত যুক্তি প্রকাশের সম্পূর্ণ মূল্যায়ন করা হবে। এটি পোস্ট বর্ধনের ফলাফল যা মুছে ফাংশন () এ পাস করা হয়। তাই হ্যাঁ মুছে ফেলার আগে (পিএমএইচ) ডাকের পোস্ট ইনক্রিমেন্ট সম্পন্ন হবে।
মার্টিন ইয়র্ক

দ্রষ্টব্য: লাইনের প্রায় লাইন স্কট মায়ারের "কার্যকর এসটিএল" আইটেম 9
মিশ্র

(স্বতঃ pm_t = Port_map.begin (); pm_it! = port_map.end ();) এর জন্য {...}
Andrey Syrokomskiy

4
@ আইবাইজার: ভেক্টরে On মুছে ফেলা () এর ব্যবহারটি অ্যারেটির সমস্ত পুনরাবৃত্তিকে মুছে ফেলার পরে (কেবল শেষ নয়) অবৈধ করে দেয়, এটি Sequenceপাত্রে সম্পত্তি । Associativeধারকগুলির বিশেষ সম্পত্তি হ'ল পুনরায় মুছে ফেলা বা সন্নিবেশ দ্বারা অকার্যকর হয় না (যদি না তারা মুছে ফেলা উপাদানটির দিকে নির্দেশ না করে)। ভেক্টর করা এবং মোছা usign iterators উপযুক্ত প্রশ্নে বিস্তারিতভাবে আচ্ছাদিত করা হয় stackoverflow.com/a/3938847/14065
মার্টিন ইয়র্ক

12

এখানে আমি কীভাবে এটি করছি ...

typedef map<string, string>   StringsMap;
typedef StringsMap::iterator  StrinsMapIterator;

StringsMap m_TheMap; // Your map, fill it up with data    

bool IsTheOneToDelete(string str)
{
     return true; // Add your deletion criteria logic here
}

void SelectiveDelete()
{
     StringsMapIter itBegin = m_TheMap.begin();
     StringsMapIter itEnd   = m_TheMap.end();
     StringsMapIter itTemp;

     while (itBegin != itEnd)
     {
          if (IsTheOneToDelete(itBegin->second)) // Criteria checking here
          {
               itTemp = itBegin;          // Keep a reference to the iter
               ++itBegin;                 // Advance in the map
               m_TheMap.erase(itTemp);    // Erase it !!!
          }
          else
               ++itBegin;                 // Just move on ...
     }
}

আপনি যদি ভেক্টরের শেষটিও মুছে ফেলেন (এটি শেষ হয়), তবে শেষ চেকটি (কিছুক্ষণ শর্ত) একটি অবৈধ পুনরাবৃত্তকারী (এটি) এর বিরুদ্ধে হবে। ভাল না.
অ্যাগোস্টিনো

1

আমি প্রায় এটিই করতাম:

bool is_remove( pair<string, SerialdMsg::SerialFunction_t> val )
{
    return val.second == delete_this_id;
}

map<string, SerialdMsg::SerialFunction_t>::iterator new_end = 
    remove_if (port_map.begin( ), port_map.end( ), is_remove );

port_map.erase (new_end, port_map.end( ) );

কিছুটা অদ্ভুত বিষয় আছে

val.second == delete_this_id

তবে আমি এটি কেবল আপনার উদাহরণ কোড থেকে অনুলিপি করেছি।

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