2008-10-07 20 views
28

मेरे पास लगभग निम्न कोड है। क्या यह अच्छा या अधिक कुशल बनाया जा सकता है? शायद std::remove_if का उपयोग कर रहे हैं? क्या आप इसे ट्रैक करते समय मानचित्र से आइटम हटा सकते हैं? क्या हम अस्थायी मानचित्र का उपयोग करने से बच सकते हैं?std :: मानचित्र से आइटम कैसे फ़िल्टर करें?

typedef std::map<Action, What> Actions; 
static Actions _actions; 

bool expired(const Actions::value_type &action) 
{ 
    return <something>; 
} 

void bar(const Actions::value_type &action) 
{ 
    // do some stuff 
} 

void foo() 
{ 
    // loop the actions finding expired items 
    Actions actions; 
    BOOST_FOREACH(Actions::value_type &action, _actions) 
    { 
    if (expired(action)) 
     bar(action); 
    else 
     actions[action.first]=action.second; 
    } 
    } 
    actions.swap(_actions); 
} 

उत्तर

30

आप मिटाएं() का उपयोग कर सकते हैं, लेकिन मुझे नहीं पता कि BOOST_FOREACH अवैध इटरेटर को कैसे संभालेगा। documentation for map::erase बताता है कि केवल मिटाए गए इटरेटर को अमान्य कर दिया जाएगा, अन्य ठीक होना चाहिए।

Actions::iterator it = _actions.begin(); 
while (it != _actions.end()) 
{ 
    if (expired(*it)) 
    { 
    bar(*it); 
    Actions::iterator toerase = it; 
    ++it; 
    _actions.erase(toerase); 
    } 
    else 
    ++it; 
} 
+0

धन्यवाद, कि मोटे तौर पर क्या मैं भी –

1

विचार की अवधि समाप्त हो आइटम हटाने के लिए है, तो क्यों map::erase का उपयोग नहीं? इस तरह आपको केवल उन तत्वों को हटाना होगा जिनकी आपको आवश्यकता नहीं है, उन सभी तत्वों के साथ एक संपूर्ण प्रति पुनर्निर्माण न करें जिन्हें आप रखना चाहते हैं।

जिस तरह से आप ऐसा करेंगे, उन तत्वों को इंगित करने वाले इटरेटर को सहेजना है जिन्हें आप मिटाना चाहते हैं, फिर पुनरावृत्ति खत्म हो जाने के बाद उन्हें मिटा दें।

या, आप जिस तत्व को देखते हैं उसे सहेज सकते हैं, अगले तत्व पर जा सकते हैं, और फिर अस्थायी मिटा सकते हैं। लूप सीमाएं आपके मामले में गड़बड़ हो जाती हैं, इसलिए आपको खुद को पुनरावृत्ति को ठीक करना होगा।

कैसे समाप्त() लागू किया गया है, इस पर निर्भर करता है कि अन्य बेहतर तरीके भी हो सकते हैं। उदाहरण के लिए यदि आप नक्शा की कुंजी के रूप में टाइमस्टैम्प का ट्रैक रखते हैं (जैसा कि समाप्त हो गया है) का तात्पर्य है?), आप वर्तमान टाइमस्टैम्प पर ऊपरी_बाउंड कर सकते हैं, और श्रेणी के सभी तत्व [start(), upper_bound()) की आवश्यकता है संसाधित और मिटाया जाना है।

1

कुछ कोई भी कभी भी है कि मिटा एक नया, इसकी गारंटी-टू-बी-मान्य iterator देता है, जब किसी भी कंटेनर पर प्रयोग किया जाता है पता करने के लिए लगता है कि यहां तरीका देखें: मैं भीतरी पाश पुनर्गठन करेंगे।

Actions::iterator it = _actions.begin(); 
while (it != _actions.end()) 
{ 
    if (expired(*it)) 
    { 
    bar(*it); 
    it = _actions::erase(it); 
    } 
    else 
    ++it; 
} 

भंडारण actions.end() शायद इस मामले के बाद से इटरेटर स्थिरता की गारंटी नहीं है में एक अच्छी योजना नहीं है, मेरा मानना ​​है कि।

+0

के साथ आया प्रलेखन मैं अपने जवाब में जुड़ा हुआ है, शून्य रिटर्न मिटा के अनुसार, और अपने कोड नमूना संकलन नहीं होगा। –

+0

यह वीसी ++ में एक विस्तार है, मुझे लगता है कि –

+0

यह किसी भी कंटेनर के लिए सच नहीं है, केवल वे अनुक्रम के मॉडल हैं। कंटेनरों के लिए जो एसोसिएटिव कंटेनर का मॉडल हैं, मिटाने के पास शून्य का रिटर्न प्रकार है। – camh

51

मार्क रान्ससम एल्गोरिदम की एक भिन्नता लेकिन अस्थायी की आवश्यकता के बिना।

for(Actions::iterator it = _actions.begin();it != _actions.end();) 
{ 
    if (expired(*it)) 
    { 
     bar(*it); 
     _actions.erase(it++); // Note the post increment here. 
           // This increments 'it' and returns a copy of 
           // the original 'it' to be used by erase() 
    } 
    else 
    { 
     ++it; // Use Pre-Increment here as it is more effecient 
       // Because no copy of it is required. 
    } 
} 
+3

अच्छी तरह से किया गया। बहुत बुरा यह इस परिष्करण को देखने के लिए मुझे 2 1/2 साल लगे। –

+1

@ मार्क रान्ससम: यह ठीक है। हम अभी भी इसे 'मार्क रान्ससम तकनीक' कह सकते हैं :-) –

+0

धन्यवाद @ मार्क रान्ससम और @ मार्टिन। उस कोड में बहुत अधिक जानकारी। मैंने हमेशा सोचा कि स्ट्राउस्ट्रप ने ++ i क्यों पसंद किया। – matiu

संबंधित मुद्दे