2012-07-27 15 views
7

के लिए कस्टम इंसर्टर std::vector को देखते हुए जिसमें MyClass की ऑब्जेक्ट्स हैं। मैं एक और वेक्टर कैसे बना सकता हूं जिसमें std::copy का उपयोग करके MyClass के एक सदस्य का डेटा हो? मुझे लगता है कि मुझे एक कस्टम back_inserter लागू करना होगा, लेकिन मैं यह नहीं समझ पाया कि अब तक यह कैसे करें।std :: copy

struct MyClass { 
    int a; 
} 

std::vector<MyClass> vec1; 

// I could copy that to another vector of type MyClass using std::copy. 
std::copy(vec1.begin(), vec1.end(); std::back_inserter(someOtherVec) 

// However I want just the data of the member a, how can I do that using std::copy? 
std::vector<int> vec2; 
+1

'std :: copy' तत्वों को संशोधित किए बिना सादे प्रतिलिपि के लिए है। 'std :: transform' आपको प्रत्येक तत्व में परिवर्तन लागू करने की अनुमति देता है, और उसके बाद रूपांतरण के आउटपुट को संग्रहीत करता है। जो आप चाहते हैं वही है। :) – jalf

+0

वाह बहुत सारे जवाब, thx! – Nils

उत्तर

15

Use std::transform इसके लिए।

std::transform(vec1.begin(), vec1.end(), std::back_inserter(vec2), 
       [](const MyClass& cls) { return cls.a; }); 

(आप सी ++ 11 उपयोग नहीं कर सकते हैं, तो आप कर सकते हैं एक समारोह ऑब्जेक्ट को स्वयं:

struct AGetter { int operator()(const MyClass& cls) const { return cls.a; } }; 

std::transform(vec1.begin(), vec1.end(), std::back_inserter(vec2), AGetter()); 

या std::tr1::bind उपयोग करें यदि आप उपयोग कर सकते हैं TR1:

std::transform(vec1.begin(), vec1.end(), std::back_inserter(vec2), 
       std::tr1::bind(&MyClass::a, std::tr1::placeholders::_1)); 

बीटीडब्ल्यू, जैसा कि @ नवाज ने टिप्पणी की है, प्रतिलिपि के दौरान अनावश्यक पुनर्वितरण को रोकने के लिए .reserve() करें।

vec2.reserve(vec1.size()); 
std::transform(...); 
+0

मेरी इच्छा है कि मेरे पास काम पर सी ++ 11 था .. लेकिन यह w/o lambdas भी किया जा सकता है। – Nils

+0

'std :: back_inserter' का उपयोग करने से पहले' vec2' पर 'रिजर्व()' को कॉल करना बेहतर है। – Nawaz

+1

आप 'std :: bind' का उपयोग 'std :: transform' के साथ पूरे' AGetter' को छोड़ने के लिए कर सकते हैं। – Flexo

4

आप std::transform नहीं std::copy और std::bind उपयोग करने के लिए एक सदस्य चर के लिए सूचक करने के लिए बाध्य करना चाहते हैं:

#include <algorithm> 
#include <iterator> 
#include <vector> 
#include <iostream> 
#include <functional> 

struct foo { 
    int a; 
}; 

int main() { 
    const std::vector<foo> f = {{0},{1},{2}}; 
    std::vector<int> out; 

    out.reserve(f.size()); 
    std::transform(f.begin(), f.end(), std::back_inserter(out), 
       std::bind(&foo::a, std::placeholders::_1)); 

    // Print to prove it worked: 
    std::copy(out.begin(), out.end(), std::ostream_iterator<int>(std::cout, "\n")); 
} 

मेरे उदाहरण सी ++ 11 है, लेकिन आप काम वेक्टर initalization को छोड़ अगर और boost::bind का उपयोग करें, इसके बजाय यह सी ++ 11 के बिना भी काम करता है।

+1

यदि आप सी ++ 11 का उपयोग कर रहे हैं, तो 'std :: bind' के बजाय लैम्ब्डा का उपयोग क्यों न करें? – Nawaz

+0

साधारण चीजों के लिए मैं व्यक्तिगत रूप से बाइंडर सिंटैक्स पसंद करता हूं। यह शर्म की बात है कि प्लेसहोल्डर्स को अपना नामस्थान मिला, लेकिन इसके साथ ही बराबर लैम्ब्डा की तुलना में यह कम वर्बोज़ है। – Flexo

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