2010-05-03 41 views

उत्तर

61

ऑपरेटर से कम अधिभार, फिर क्रमबद्ध करें। यह एक उदाहरण मैं वेब बंद पाया है ...

class MyData 
{ 
public: 
    int m_iData; 
    string m_strSomeOtherData; 
    bool operator<(const MyData &rhs) const { return m_iData < rhs.m_iData; } 
}; 

std::sort(myvector.begin(), myvector.end()); 

स्रोत: here

+13

आप op <() const बनाना चाहते हैं, और इसके पैरामीटर को कॉन्स्ट संदर्भ के रूप में पास करना चाहते हैं। –

+15

@Neil, मैंने पाया उदाहरण मैंने पोस्ट किया क्योंकि मेरे पास यह सब दोस्त टाइप करने का समय नहीं था। आईटी एक ठोस उदाहरण था और समस्या हल हो गई। मुझे खुशी है कि इसे कम करने के लिए आपको 40 मिनट का समय लगता है। अगर मैं स्रोत साइट शामिल नहीं करता, तो मैं इसे नीचे वोट दिया जा सकता था, लेकिन मैंने किया। ऐसा नहीं है कि मैंने इसे अपने आप के रूप में बंद करने की कोशिश की। – Gabe

+7

@Neil मैं मानता हूं कि यह थोड़ी देर के बाद से मैंने सी ++ का उपयोग किया है, लेकिन मुझे इस सवाल के साथ कुछ सामान्य विचार याद आया, इसलिए मैंने जवाब दिया। मैं दावा नहीं कर रहा हूं कि यह सही है, लेकिन यह काम करता है, मैंने इसे स्वयं करने की कोशिश की। मैंने आपका सुझाव लिया और इसे जोड़ा। यदि आपको इसके साथ कोई अन्य समस्या है, तो इसके बजाय बोलने के बजाय बोलें। इस तरह अभिनय करना एसओडी या तो दोस्त के बारे में नहीं था। – Gabe

94
std::sort(object.begin(), object.end(), pred()); 

जहां, pred() एक समारोह वस्तु myclass की वस्तुओं पर आदेश को परिभाषित है। वैकल्पिक रूप से, आप myclass::operator< को परिभाषित कर सकते हैं।

std::sort(object.begin(), object.end(), 
      [] (myclass const& a, myclass const& b) { return a.v < b.v; }); 

या यदि आप सी ++ 03 के साथ फंस रहे हैं, समारोह वस्तु दृष्टिकोण (v सदस्य है जिस पर आप क्रमबद्ध करना चाहते है):

उदाहरण के लिए, यदि आप एक लैम्ब्डा पारित कर सकते हैं

struct pred { 
    bool operator()(myclass const & a, myclass const & b) const { 
     return a.v < b.v; 
    } 
}; 
+0

कि @NativeCoder क्या ऑपरेटर के लिए है जोड़कर स्टीव जेसप से जवाब फैली - आप इसे परिभाषित कर सकते हैं हालांकि आप चाहें और जो भी वैरिएबल चाहते हैं उसके अनुसार। इसे ऑपरेटर ओवरलोडिंग http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html कहा जाता है। –

+8

यदि आपके पास इस विशेष वर्ग का सामान्य क्रम नहीं है लेकिन केवल इस वेक्टर के लिए इसे सॉर्ट करना चाहते हैं तो अनुमानित दृष्टिकोण ऑपरेटर ओवरलोडिंग दृष्टिकोण से काफी बेहतर है। –

14

एक संकेतक करने वाली सदस्य आप एक ही तुलनित्र है, जो अपनी कक्षा के किसी भी डेटा के सदस्य के साथ काम कर सकते हैं लिखने के लिए अनुमति देता है :

#include <algorithm> 
#include <vector> 
#include <string> 
#include <iostream> 

template <typename T, typename U> 
struct CompareByMember { 
    // This is a pointer-to-member, it represents a member of class T 
    // The data member has type U 
    U T::*field; 
    CompareByMember(U T::*f) : field(f) {} 
    bool operator()(const T &lhs, const T &rhs) { 
     return lhs.*field < rhs.*field; 
    } 
}; 

struct Test { 
    int a; 
    int b; 
    std::string c; 
    Test(int a, int b, std::string c) : a(a), b(b), c(c) {} 
}; 

// for convenience, this just lets us print out a Test object 
std::ostream &operator<<(std::ostream &o, const Test &t) { 
    return o << t.c; 
} 

int main() { 
    std::vector<Test> vec; 
    vec.push_back(Test(1, 10, "y")); 
    vec.push_back(Test(2, 9, "x")); 

    // sort on the string field 
    std::sort(vec.begin(), vec.end(), 
     CompareByMember<Test,std::string>(&Test::c)); 
    std::cout << "sorted by string field, c: "; 
    std::cout << vec[0] << " " << vec[1] << "\n"; 

    // sort on the first integer field 
    std::sort(vec.begin(), vec.end(), 
     CompareByMember<Test,int>(&Test::a)); 
    std::cout << "sorted by integer field, a: "; 
    std::cout << vec[0] << " " << vec[1] << "\n"; 

    // sort on the second integer field 
    std::sort(vec.begin(), vec.end(), 
     CompareByMember<Test,int>(&Test::b)); 
    std::cout << "sorted by integer field, b: "; 
    std::cout << vec[0] << " " << vec[1] << "\n"; 
} 

आउटपुट:

sorted by string field, c: x y 
sorted by integer field, a: y x 
sorted by integer field, b: x y 
+0

हाय स्टीव, मैं इस समस्या के बिना एक ही समस्या को हल करने के बारे में सोच रहा हूं बिना किसी प्रगति के! आपका समाधान मेरे लिए बहुत अच्छा लग रहा है। मुझे लगता है कि अगर यह कभी भी मेरे साथ आने के लिए मुझे लंबा समय लगेगा! मैंने मायर्स के प्रभावी सी ++ और प्रभावी एसटीएल और डेहर्स्ट के सी ++ सामान्य ज्ञान को पढ़ा है। मुझे आश्चर्य है कि क्या आप कुछ और पढ़ने की सिफारिश कर सकते हैं, क्या आप किसी भी किताबों के बारे में जानते हैं जो विशेष रूप से ऊपर दिए गए उदाहरणों को कवर करता है या इस तरह के समाधान देखने में मेरी सहायता करने के लिए कोई और सामान्य सुझाव विफल रहता है? –

+1

@Czarak: इसे फिर से देखकर, यह शायद सुधार किया जा सकता है। उदाहरण के लिए, यदि सूचक के लिए सूचक टेम्पलेट पैरामीटर था तो यह बेहतर अनुकूलित हो सकता है: 'टेम्पलेट <टाइपनाम टी, टाइपनाम यू, यू (टी :: * एफ)> स्ट्रक्चर तुलनाबैम्बर 2 {बूल ऑपरेटर() (कॉन्स टी एंड एलएचएस, कॉन्स टी & rhs) {वापसी lhs। * एफ

+0

@Czarak: पढ़ने के लिए, मुझे यकीन नहीं है। यहां "चाल" टेम्पलेट्स के साथ सदस्य पॉइंटर्स का संयोजन है, मुझे लगता है कि यह आरामदायक लेखन टेम्पलेट्स होने का विषय है, और यह जानना कि उनके साथ क्या किया जा सकता है। वंदेवोर्डे और जोसुटिस की पुस्तक "सी ++ टेम्पलेट्स - द पूर्ण गाइड" अच्छी है, लेकिन मैंने इसे पढ़ा नहीं है। यह काफी पुराना और महंगा हो सकता है कि अब तक एक बेहतर विकल्प है। Http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list पर देखें। और ध्यान दें कि यदि आपके पास सी ++ 0x है, तो लैम्बडा फ़ंक्शन इस के लिए पूरी कक्षा को लिख सकता है! –

8

की तरह अन्य उत्तर में बताया गया है कि आप समर्थक की जरूरत है एक तुलना समारोह के साथ। यदि आप sort कॉल के करीब उस फ़ंक्शन की परिभाषा को रखना चाहते हैं (उदा। अगर यह केवल इस प्रकार के लिए समझ में आता है) तो आप इसे boost::lambda के साथ ठीक से परिभाषित कर सकते हैं। सदस्य फ़ंक्शन को कॉल करने के लिए boost::lambda::bind का उपयोग करें।

उदा। सदस्य चर या समारोह data1 द्वारा क्रमबद्ध करें:

#include <algorithm> 
#include <vector> 
#include <boost/lambda/bind.hpp> 
#include <boost/lambda/lambda.hpp> 
using boost::lambda::bind; 
using boost::lambda::_1; 
using boost::lambda::_2; 

std::vector<myclass> object(10000); 
std::sort(object.begin(), object.end(), 
    bind(&myclass::data1, _1) < bind(&myclass::data1, _2)); 
2

इस यह आम तौर पर हल करने के लिए मेरे दृष्टिकोण है। यह आवश्यकता को हटाकर स्पष्ट रूप से टेम्पलेट तर्क स्थापित करने के लिए और (getters) विकल्प भी तरीकों के functoins और संकेत का उपयोग करने के

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

using namespace std; 

template <typename T, typename U> 
struct CompareByGetter { 
    U (T::*getter)() const; 
    CompareByGetter(U (T::*getter)() const) : getter(getter) {}; 
    bool operator()(const T &lhs, const T &rhs) { 
     (lhs.*getter)() < (rhs.*getter)(); 
    } 
}; 

template <typename T, typename U> 
CompareByGetter<T,U> by(U (T::*getter)() const) { 
    return CompareByGetter<T,U>(getter); 
} 

//// sort_by 
template <typename T, typename U> 
struct CompareByMember { 
    U T::*field; 
    CompareByMember(U T::*f) : field(f) {} 
    bool operator()(const T &lhs, const T &rhs) { 
     return lhs.*field < rhs.*field; 
    } 
}; 

template <typename T, typename U> 
CompareByMember<T,U> by(U T::*f) { 
    return CompareByMember<T,U>(f); 
} 

template <typename T, typename U> 
struct CompareByFunction { 
    function<U(T)> f; 
    CompareByFunction(function<U(T)> f) : f(f) {} 
    bool operator()(const T& a, const T& b) const { 
     return f(a) < f(b); 
    } 
}; 

template <typename T, typename U> 
CompareByFunction<T,U> by(function<U(T)> f) { 
    CompareByFunction<T,U> cmp{f}; 
    return cmp; 
} 

struct mystruct { 
    double x,y,z; 
    string name; 
    double length() const { 
     return sqrt(x*x + y*y + z*z); 
    } 
}; 

ostream& operator<< (ostream& os, const mystruct& ms) { 
    return os << "{ " << ms.x << ", " << ms.y << ", " << ms.z << ", " << ms.name << " len: " << ms.length() << "}"; 
} 

template <class T> 
ostream& operator<< (ostream& os, std::vector<T> v) { 
    os << "["; 
    for (auto it = begin(v); it != end(v); ++it) { 
     if (it != begin(v)) { 
      os << " "; 
     } 
     os << *it; 
    } 
    os << "]"; 
    return os; 
} 

void sorting() { 
    vector<mystruct> vec1 = { {1,1,0,"a"}, {0,1,2,"b"}, {-1,-5,0,"c"}, {0,0,0,"d"} }; 

    function<string(const mystruct&)> f = [](const mystruct& v){return v.name;}; 

    cout << "unsorted " << vec1 << endl; 
    sort(begin(vec1), end(vec1), by(&mystruct::x)); 
    cout << "sort_by x " << vec1 << endl; 
    sort(begin(vec1), end(vec1), by(&mystruct::length)); 
    cout << "sort_by len " << vec1 << endl; 
    sort(begin(vec1), end(vec1), by(f)); 
    cout << "sort_by name " << vec1 << endl; 
} 
संबंधित मुद्दे