मैं stl वेक्टर के लिए एपीआई प्रलेखन को देख रहा था, और देखा कि वेक्टर वर्ग पर कोई विधि नहीं थी जो एक निश्चित मूल्य के साथ एक तत्व को हटाने की अनुमति देता था। यह एक आम ऑपरेशन की तरह लगता है, और यह अजीब लगता है कि ऐसा करने का कोई तरीका नहीं है।
मैं stl वेक्टर के लिए एपीआई प्रलेखन को देख रहा था, और देखा कि वेक्टर वर्ग पर कोई विधि नहीं थी जो एक निश्चित मूल्य के साथ एक तत्व को हटाने की अनुमति देता था। यह एक आम ऑपरेशन की तरह लगता है, और यह अजीब लगता है कि ऐसा करने का कोई तरीका नहीं है।
जवाबों:
std::remove
वास्तव में कंटेनर से तत्व को नहीं मिटाता है, लेकिन यह नए सिरे के पुनरावृत्त को लौटाता है जिसे कंटेनर के अंत में होने container_type::erase
वाले अतिरिक्त तत्वों के वास्तविक निष्कासन को करने के लिए पारित किया जा सकता है :
std::vector<int> vec;
// .. put in some values ..
int int_to_remove = n;
vec.erase(std::remove(vec.begin(), vec.end(), int_to_remove), vec.end());
vec.end()
कॉल के दोनों ओर समान होने की गारंटी है std::remove
? यह मुझे वेब के अन्य हिस्सों को पढ़ने में लगता है जैसे यह सुरक्षित है, लेकिन इसे स्पष्ट रूप से कहा जाना चाहिए।
vec.end()
समान होने की आवश्यकता नहीं है; यह सिर्फ सही होना चाहिए (जो यह है)।
vec.end()
समान होने की आवश्यकता है, लेकिन यह ठीक है क्योंकि std::remove
इसे नहीं बदलता है। यदि उसने इसे बदल दिया (और पुराने मूल्य को अमान्य कर दिया) तो एक समस्या होगी: मापदंडों के मूल्यांकन का क्रम अनिर्दिष्ट है और इसलिए आपको यह नहीं पता होगा कि यह उपयोग किए जाने तक दूसरा vec.end()
अभी भी मान्य है या नहीं । इसका कारण वही है जो सरल है, std::remove
कंटेनर का आकार नहीं बदलता है, यह सिर्फ सामग्री को इधर-उधर करता है।
std::remove
केवल एक तर्क के साथ लेता है; वह यह है कि const char *_Filename
। मुझे किस विधि से कॉल करने की आवश्यकता है?
remove
फ़ाइल का संस्करण है जो किसी फ़ाइल को हटा देता है। कंटेनर के साथ उस सौदे <algorithm>
के संस्करण का उपयोग करने के लिए आपको शामिल करने की आवश्यकता है remove
।
यदि आप किसी आइटम को निकालना चाहते हैं , तो निम्नलिखित कुछ अधिक कुशल होगा।
std::vector<int> v;
auto it = std::find(v.begin(), v.end(), 5);
if(it != v.end())
v.erase(it);
या आप आइटम को स्थानांतरित करने से बच सकते हैं यदि ऑर्डर आपके लिए मायने नहीं रखता है:
std::vector<int> v;
auto it = std::find(v.begin(), v.end(), 5);
if (it != v.end()) {
using std::swap;
// swap the one to be removed with the last element
// and remove the item at the end of the container
// to prevent moving all items after '5' by one
swap(*it, v.back());
v.pop_back();
}
वैश्विक विधि एसटीडी का प्रयोग करें: शुरुआत और अंत के साथ हटानेवाला, और उसके बाद एसटीडी का उपयोग करें: वेक्टर। वास्तव में तत्वों को हटाने के लिए।
दस्तावेज़ लिंक
एसटीडी :: http://www.cppreference.com/cppalgorithm/remove.html
std :: वेक्टर . erase http://www.cppreference.com/cppvector/erase.html निकालें
std::vector<int> v;
v.push_back(1);
v.push_back(2);
//Vector should contain the elements 1, 2
//Find new end iterator
std::vector<int>::iterator newEnd = std::remove(v.begin(), v.end(), 1);
//Erase the "removed" elements.
v.erase(newEnd, v.end());
//Vector should now only contain 2
मेरी त्रुटि को इंगित करने के लिए जिम बक का धन्यवाद।
अन्य उत्तर इसे अच्छी तरह से करने के लिए कवर करते हैं, लेकिन मैंने सोचा कि मैं यह भी बताऊंगा कि यह वास्तव में अजीब नहीं है कि यह वेक्टर एपीआई में नहीं है: यह अकुशल है, मान के लिए वेक्टर के माध्यम से रैखिक खोज, इसके बाद एक गुच्छा। इसे हटाने के लिए नकल की।
यदि आप इस ऑपरेशन को गहनता से कर रहे हैं, तो यह इस कारण के बजाय std :: सेट पर विचार करने के लायक हो सकता है।
यदि आपके पास एक अनसुलझा वेक्टर है, तो आप बस अंतिम वेक्टर तत्व के साथ स्वैप कर सकते हैं resize()
।
एक आदेश दिया कंटेनर के साथ, आप के साथ सबसे अच्छा बंद हो जाएगा std::vector::erase()
। ध्यान दें कि वहाँ एक std::remove()
परिभाषित है <algorithm>
, लेकिन यह वास्तव में मिटा नहीं है। (ध्यान से प्रलेखन पढ़ें)।
एक छोटा समाधान (जो आपको वेक्टर नाम को 4 बार दोहराने के लिए मजबूर नहीं करता है) बूस्ट का उपयोग करना होगा:
#include <boost/range/algorithm_ext/erase.hpp>
// ...
boost::remove_erase(vec, int_to_remove);
Http://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference/algorithms/new/remove_erase.html देखें
से c ++ 20 :
एक गैर-सदस्यीय कार्य शुरू किया गया std::erase
, जो इनपुट के रूप में हटाए जाने वाले वेक्टर और मूल्य को लेता है।
उदाहरण के लिए:
std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);
map::erase
!
स्टड भी देखें :: remove_if एक विधेय का उपयोग करने में सक्षम होने के लिए ...
यहाँ ऊपर दिए गए लिंक से उदाहरण दिया गया है:
vector<int> V;
V.push_back(1);
V.push_back(4);
V.push_back(2);
V.push_back(8);
V.push_back(5);
V.push_back(7);
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
// The output is "1 4 2 8 5 7"
vector<int>::iterator new_end =
remove_if(V.begin(), V.end(),
compose1(bind2nd(equal_to<int>(), 0),
bind2nd(modulus<int>(), 2)));
V.erase(new_end, V.end()); [1]
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
// The output is "1 5 7".
यदि आप इसे बिना किसी अतिरिक्त के करना चाहते हैं:
vector<IComponent*> myComponents; //assume it has items in it already.
void RemoveComponent(IComponent* componentToRemove)
{
IComponent* juggler;
if (componentToRemove != NULL)
{
for (int currComponentIndex = 0; currComponentIndex < myComponents.size(); currComponentIndex++)
{
if (componentToRemove == myComponents[currComponentIndex])
{
//Since we don't care about order, swap with the last element, then delete it.
juggler = myComponents[currComponentIndex];
myComponents[currComponentIndex] = myComponents[myComponents.size() - 1];
myComponents[myComponents.size() - 1] = juggler;
//Remove it from memory and let the vector know too.
myComponents.pop_back();
delete juggler;
}
}
}
}
दो तरीके हैं जिनके द्वारा आप किसी आइटम को विशेष रूप से मिटाने के लिए उपयोग कर सकते हैं। चलो एक वेक्टर ले लो
std :: vector < int > v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(40);
v.push_back(50);
1) गैर कुशल तरीका: हालांकि यह काफी कुशल प्रतीत होता है, लेकिन यह नहीं है क्योंकि फ़ंक्शन को मिटाता है तत्वों को छोड़ देता है और सभी तत्वों को बाईं ओर 1 से स्थानांतरित कर देता है। इसलिए इसकी जटिलता ओ होगी (n ^ 2)
std :: vector < int > :: iterator itr = v.begin();
int value = 40;
while ( itr != v.end() )
{
if(*itr == value)
{
v.erase(itr);
}
else
++itr;
}
2) कुशल तरीका (सिफारिश) : इसे ERASE - REMOVE मुहावरों के रूप में भी जाना जाता है ।
निकालें एल्गोरिदम का आउटपुट है:
10 20 30 50 40 50
वापसी के प्रकार के रूप में उस सीमा के नए सिरे पर पुनरावृत्ति होती है।
template <class ForwardIterator, class T>
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);
वेक्टर के नए सिरे से पुराने सिरे तक तत्वों को हटाने के लिए अब वेक्टर के इरेज़ फ़ंक्शन का उपयोग करें। इसके लिए O (1) समय की आवश्यकता होती है।
v.erase ( std :: remove (v.begin() , v.end() , element ) , v.end () );
इसलिए यह विधि O (n) में काम करती है
*
C ++ समुदाय ने आपका अनुरोध सुना है :)
*
C ++ 20 अब इसे करने का एक आसान तरीका प्रदान करता है। यह उतना ही सरल है:
#include <vector>
...
vector<int> cnt{5, 0, 2, 8, 0, 7};
std::erase(cnt, 0);
आप की जांच करनी चाहिए std :: मिटा और std :: erase_if ।
न केवल यह मूल्य के सभी तत्वों को हटा देगा (यहाँ '0'), यह इसे O (n) में करेगा समय की जटिलता में करेगा। जो बहुत ही बेहतरीन है जो आपको मिल सकता है।
यदि आपका संकलक C ++ 20 का समर्थन नहीं करता है, तो आपको मिटाने-हटाने के मुहावरे का उपयोग करना चाहिए :
#include <algorithm>
...
vec.erase(std::remove(vec.begin(), vec.end(), 0), vec.end());