2010-01-18 2 views
10

में सेट से सभी पूर्णांक को कैसे हटाएं I C++ में नया हूं। मैं जानना चाहता हूं कि कैसे अनुभवी कोडर ऐसा करते हैं। सी ++

मैं क्या है:

set<int> s; 
s.insert(1); 
s.insert(2); 
s.insert(3); 
s.insert(4); 
s.insert(5); 

for(set<int>::iterator itr = s.begin(); itr != s.end(); ++itr){ 
if (!(*itr % 2)) 
    s.erase(itr); 
} 

और हां, यह काम नहीं करता। क्योंकि इसे मिटा दिए जाने के बाद इसे बढ़ाया जाता है। क्या इसका मतलब यह है कि सेट से तत्व को मिटाने के बाद इसे हर बार सेट की शुरुआत को इंगित करना होगा?

उत्तर

16
for(set<int>::iterator itr = s.begin(); itr != s.end();){ 
    if (!(*itr % 2)) 
     s.erase(itr++); 

    else ++itr; 
} 

प्रभावी एसटीएल remove_if और के संयोजन मिटा

s.erase(remove_if(s.begin(), s.end(), evenOddFunctor), s.end()) 

यह उपयोगी होगा http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove

इसके अलावा स्कॉट Meyers

Edit द्वारा प्रभावी एसटीएल का संदर्भ लें: हालांकि मेरी समाधान गलत मैं इसे हटाने नहीं कर रहा हूँ। यह मेरे जैसे किसी के लिए अच्छी शिक्षा हो सकती है जो परिवर्तनीय/अपरिवर्तनीय इटरेटर्स

+0

आपके पास कोड में अतिरिक्त ब्रैकेट है। – qba

+0

मिटाने के फ़ंक्शन में itr ++ क्यों अनुमति है, लेकिन बाहर नहीं? – Quincy

+5

'itr ++' को बाहर की अनुमति है, लेकिन जब मूल्य अप्रयुक्त होता है तो '++ it' सामान्य रूप से बेहतर होता है, किसी भी समय किसी भी समय यह करने के लिए कठिन होने के कारणों के लिए ;-) इस मामले में, यह बेहतर हो सकता है सामान्य अच्छे अभ्यास को अनदेखा करें और 'itr ++' लिखें, सिर्फ इसलिए कि दोनों मामलों में कोड समान चिकना पढ़ता है। –

11

std :: set से किसी तत्व को मिटाना केवल उस तत्व को इंगित करने वाले इटरेटर्स को अमान्य करता है।

लक्ष्य तत्व को मिटाने से पहले अगले तत्व में एक पुनरावर्तक प्राप्त करें।

8

आपको शुरुआत में वापस जाने की आवश्यकता नहीं है। set::erase केवल iterators है कि आइटम मिटाया जा रहा का उल्लेख अमान्य कर देता है, तो आप सिर्फ मिटाने से पहले इटरेटर और वेतन वृद्धि की नकल करने की जरूरत है: स्कॉट मायर्स

+0

ठीक है, मैं हार मानता हूं। बग क्या है? –

+1

मैं गलत था, मैंने सोचा था कि आप पहले तत्व को छोड़ रहे थे। मैं अपनी टिप्पणी और डाउनवोट वापस लेता हूं। –

-1

सबसे अच्छा तरीका है का उपयोग करना है

for(set<int>::iterator itr = s.begin(); itr != s.end();) 
{ 
    set<int>::iterator here = itr++; 
    if (!(*here % 2)) 
     s.erase(here); 
} 
+6

'remove_if' के लिए आवश्यक है कि 'ऑपरेटर *' एक गैर-कॉन्स लैवल्यू देता है। std :: सेट लागू करता है कि यह हमेशा आदेश दिया जाता है; 'std :: set :: ऑपरेटर *' से एक गैर-कॉन्स लैवल्यू लौटने से वह गारंटी टूट जाएगी। इसलिए 'std :: remove_if()' 'std :: set :: iterator's – MSalters

+0

नहीं लेता है धन्यवाद, मुझे पता है कि –

+5

यह वास्तव में सहायक था। मैं remove_if के साथ ऐसा करने की कोशिश कर रहा हूं और इससे मुझे बताया गया कि समस्या क्या थी। धन्यवाद। –