2016-04-03 7 views
16

std::vector या किसी अन्य कंटेनर से किसी निश्चित संपत्ति वाले तत्वों को निकालने का कार्य स्वयं को कार्यात्मक शैली कार्यान्वयन के लिए उधार देता है: लूप, मेमोरी डिलोकेशन और सही ढंग से डेटा को स्थानांतरित करने से परेशान क्यों?क्या वेक्टर से तत्वों को निकालने के लिए std :: remove_if का बेहतर विकल्प है?

std::vector<int> ints; 
... 
ints.erase(
    std::remove_if(ints.begin(), 
        ints.end(), 
        [](int x){return x < 0;}), 
    ints.end()); 

यह उदाहरण सभी तत्वों को एक पूर्णांक वेक्टर से शून्य से भी कम समय निकालता है:

हालांकि सी ++ में ऐसा करने का मानक तरीका निम्नलिखित मुहावरा हो रहा है।

मुझे यह न केवल बदसूरत बल्कि गलत तरीके से उपयोग करना आसान लगता है। यह स्पष्ट है कि std::remove_if वेक्टर के आकार को बदल नहीं सकता है (जैसा कि इसका नाम सुझाएगा) क्योंकि यह केवल इटरेटर पास हो जाता है। लेकिन मेरे समेत कई डेवलपर्स, शुरुआत में नहीं पाते हैं।

तो क्या यह हासिल करने के लिए एक सुरक्षित और उम्मीदवार अधिक सुरुचिपूर्ण तरीका है? यदि नहीं, क्यों?

+1

प्रिंट हमेशा की तरह, अगर यह जटिल हो जाता है, एक (टेम्पलेट) समारोह में लपेट। –

+0

@ करोलो हॉर्वथ: हाँ, लेकिन यह एक आम काम है। मैं इसके लिए अपना खुद का काम नहीं लिखना चाहता हूं। यह मानक पुस्तकालय में है, बस अन्य भाषाओं की तरह। –

+0

हाँ, सुनिश्चित करें, प्रार्थना करें या एक प्रस्ताव लिखें और कुछ सालों तक प्रतीक्षा करें। * Facepalm *। –

उत्तर

19

मुझे यह न केवल बदसूरत बल्कि गलत तरीके से उपयोग करना आसान लगता है।

चिंता न करें, हम सभी ने शुरुआत में किया था।

यह स्पष्ट है कि std :: remove_if वेक्टर के आकार को बदल नहीं सकता है (जैसा कि इसका नाम सुझाएगा) क्योंकि यह केवल इटरेटर पास हो जाता है। लेकिन मेरे समेत कई डेवलपर्स, शुरुआत में नहीं पाते हैं।

वही। यह सबको भ्रमित करता है। शायद उन सभी वर्षों पहले इसे remove_if नहीं कहा जाना चाहिए था। हिंदसाइट, आह?

तो क्या यह हासिल करने के लिए एक सुरक्षित और उम्मीदवार अधिक सुरुचिपूर्ण तरीका है?

नहीं

यदि नहीं, तो क्यों?

क्योंकि यह एक सुरक्षित, सबसे सुरुचिपूर्ण तरीका है जो किसी कंटेनर से आइटम को हटाते समय प्रदर्शन को संरक्षित करता है जिसमें किसी आइटम को हटाने से इटरेटर को अमान्य कर दिया जाता है।

की आशंका:

कुछ भी मैं कर सकता है?

हाँ, एक समारोह में इस मुहावरे लपेट

template<class Container, class F> 
auto erase_where(Container& c, F&& f) 
{ 
    return c.erase(std::remove_if(c.begin(), 
            c.end(), 
            std::forward<F>(f)), 
        c.end());  
} 

को प्रेरित करने के उदाहरण में कॉल तो हो जाता है:

auto is_negative = [](int x){return x < 0;}; 
erase_where(ints, is_negative); 

या

erase_where(ints, [](int x){return x < 0;}); 
+0

'remove_erase_if' नहीं'? ;) – Yakk

+1

@Yakk _if * पिछले * है। नया काला कहाँ है। –

+1

@Yakk LibFun2 में आ रहा है http://en.cppreference.com/w/cpp/experimental/vector/erase_if – TemplateRex

9

इस में उपलब्ध हो जाएगाके माध्यम से जल्द ही एक सी ++ 17-तैयार कंपाइलरएल्गोरिथ्म:

#include <algorithm> 
#include <iostream> 
#include <iterator> 
#include <vector> 
#include <experimental/vector> 

int main() 
{ 
    std::vector<int> ints { -1, 0, 1 }; 
    std::experimental::erase_if(ints, [](int x){ 
     return x < 0; 
    }); 
    std::copy(ints.begin(), ints.end(), std::ostream_iterator<int>(std::cout, ",")); 
} 

Live Example कि 0,1

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