تسلسل يأمر المسندات (على سبيل المثال عن الأمراض المنقولة جنسيا :: الفرز)

StackOverflow https://stackoverflow.com/questions/274951

سؤال

ويمكنك تمرير مؤشر وظيفة، وظيفة الكائن (أو دفعة امدا) إلى الأمراض المنقولة جنسيا :: الفرز لتحديد ترتيب ضعف الدقيق للعناصر الحاوية التي تريد فرزها.

ولكن، في بعض الأحيان (يكفي أن لقد ضرب هذا عدة مرات)، وتريد أن تكون قادرة على سلسلة مقارنات "البدائية".

ومن الأمثلة تافهة يكون لو كنت فرز مجموعة من الكائنات التي تمثل بيانات للإتصال به. في بعض الأحيان سوف تحتاج لترتيب النتائج بحسب

last name, first name, area code
. وفي أحيان أخرى
first name, last name
- بعد أوقات أخرى
age, first name, area code
... الخ

والآن، يمكنك بالتأكيد إرسال كائن وظيفة إضافية لكل حالة، ولكن هذا يخالف مبدأ جاف - وخاصة إذا كان كل المقارنة أقل تافهة

ويبدو أن يجب أن تكون قادرا على كتابة التسلسل الهرمي للوظائف المقارنة - تلك مستوى منخفض تفعل واحدة، بدائية، مقارنات (مثل الاسم الأول <الاسم الأول)، ثم أعلى تدعو منها مستوى تلك المستوى الأدنى في الخلافة ( ربما تسلسل مع && الاستفادة من تقييم ماس كهربائى) لتوليد وظائف المركبة.

والمشكلة مع هذا النهج هو أن الأمراض المنقولة جنسيا :: نوع يأخذ المسند ثنائي - المسند لا يمكن أن ترجع منطقي. حتى إذا كنت يؤلف لهم لا يمكنك معرفة ما إذا كان "كاذبة" يشير إلى المساواة أو أكبر من. يمكنك جعل المسندات مستوى أقل عودتك عدد صحيح، مع ثلاث ولايات - ولكن بعد ذلك سيكون لديك للالتفاف تلك الموجودة في المسندات مستوى أعلى قبل أن يتمكنوا من استخدامها مع الأمراض المنقولة جنسيا :: نوع من تلقاء نفسها

في كل شيء، هذه ليست مشاكل مستعصية على الحل. يبدو مجرد أصعب مما ينبغي - وبالتأكيد تدعو إلى تنفيذ مكتبة المساعد

لذلك، لا أحد يعرف من أي مكتبة موجودة من قبل (خاصة لو كان الأمراض المنقولة جنسيا أو تعزيز المكتبة.) التي يمكن أن تساعد هنا - من لديه أية أفكار أخرى في هذا الشأن

و[تحديث]

وكما ذكر في بعض التعليقات - لقد ذهبت إلى الأمام ومكتوبة تنفيذ بلدي من فئة لإدارة هذا. انها الحد الأدنى إلى حد ما، وربما لديه بعض القضايا معها بشكل عام. ولكن على هذا الأساس، لكل مهتم، الطبقة هنا:

http://pastebin.com/f52a85e4f

وبعض وظائف المساعد (لتجنب الحاجة إلى تحديد وسائط قالب) هنا هو:

http://pastebin.com/fa03d66e

هل كانت مفيدة؟

المحلول

هل يمكن بناء نظام تسلسل القليل مثل ذلك:

struct Type {
  string first, last;
  int age;
};

struct CmpFirst {
  bool operator () (const Type& lhs, const Type& rhs) { return lhs.first < rhs.first; }
};

struct CmpLast {
  bool operator () (const Type& lhs, const Type& rhs) { return lhs.last < rhs.last; }
};

struct CmpAge {
  bool operator () (const Type& lhs, const Type& rhs) { return lhs.age < rhs.age; }
};

template <typename First, typename Second>
struct Chain {
  Chain(const First& f_, const Second& s_): f(f_), s(s_) {}

  bool operator () (const Type& lhs, const Type& rhs) {
    if(f(lhs, rhs))
      return true;
    if(f(rhs, lhs))
      return false;

    return s(lhs, rhs);
  }

  template <typename Next>
  Chain <Chain, Next> chain(const Next& next) const {
     return Chain <Chain, Next> (*this, next);
  }

  First f;
  Second s;
};

struct False { bool operator() (const Type& lhs, const Type& rhs) { return false; } };

template <typename Op>
Chain <False, Op> make_chain(const Op& op) { return Chain <False, Op> (False(), op); }

وبعد ذلك لاستخدامه:

vector <Type> v;  // fill this baby up

sort(v.begin(), v.end(), make_chain(CmpLast()).chain(CmpFirst()).chain(CmpAge()));

والسطر الأخير هو مطول بعض الشيء، ولكن أعتقد أنه من الواضح ما المقصود.

نصائح أخرى

واحد الطريقة التقليدية للتعامل مع هذا هي لفرز في ممرات متعددة واستخدام نوع مستقر. لاحظ أن std::sort عموما <م> لا مستقرة. ومع ذلك، هناك std::stable_sort.

وقال ذلك، أود أن أكتب التفاف حول [فونكتورس] التي تقوم بإرجاع خاص بثلاث ولايات (تمثل أقل، يساوي، أكبر).

ويمكنك أن تجرب هذا:

والاستعمال:

struct Citizen {
    std::wstring iFirstName;
    std::wstring iLastName;
};

ChainComparer<Citizen> cmp;
cmp.Chain<std::less>( boost::bind( &Citizen::iLastName, _1 ) );
cmp.Chain<std::less>( boost::bind( &Citizen::iFirstName, _1 ) );

std::vector<Citizen> vec;
std::sort( vec.begin(), vec.end(), cmp );

والتنفيذ:

template <typename T>
class ChainComparer {
public:

    typedef boost::function<bool(const T&, const T&)> TComparator;
    typedef TComparator EqualComparator;
    typedef TComparator CustomComparator;

    template <template <typename> class TComparer, typename TValueGetter>
    void Chain( const TValueGetter& getter ) {

        iComparers.push_back( std::make_pair( 
            boost::bind( getter, _1 ) == boost::bind( getter, _2 ), 
            boost::bind( TComparer<TValueGetter::result_type>(), boost::bind( getter, _1 ), boost::bind( getter, _2 ) ) 
        ) );
    }

    bool operator()( const T& lhs, const T& rhs ) {
        BOOST_FOREACH( const auto& comparer, iComparers ) {
            if( !comparer.first( lhs, rhs ) ) {
                return comparer.second( lhs, rhs );
            }
        }

        return false;
    }

private:
    std::vector<std::pair<EqualComparator, CustomComparator>> iComparers;
};
ليس مضمونا

وstd::sort أن تكون مستقرة لأنواع مستقرة وعادة ما تكون أبطأ من تلك غير مستقرة ... ذلك باستخدام نوع مستقر عدة مرات يشبه وصفة للمتاعب الأداء ...

ونعم انها حقا من العار أن نسأل نوع لالمسند: لا أرى أي وسيلة أخرى من إنشاء functor قبول ناقلات وظائف خاص بثلاث ولايات ...

والحل هو تسلسل مطول. يمكنك أيضا استخدام دفعة :: ربط بالتزامن مع الأمراض المنقولة جنسيا :: logical_and لبناء المسند الفرز الخاص بك. راجع مقالة مرتبطة لمزيد من المعلومات: <لأ href = "http://www.informit.com/articles/article.aspx؟p=412354&seqNum=4" يختلط = "نوفولو noreferrer" عنوان = "كيف يمكن للمكتبة دفعة مأزق تحسين ++ C البرامج بك "> كيف المكتبة دفعة مأزق يمكن أن يحسن بك C ++ برامج

وVariadic قوالب في C ++ 11 إعطاء الخيار أقصر:

    #include <iostream>
    using namespace std;

    struct vec { int x,y,z; };

    struct CmpX {
      bool operator() (const vec& lhs, const vec& rhs) const 
      { return lhs.x < rhs.x; }
    };

    struct CmpY {
      bool operator() (const vec& lhs, const vec& rhs) const 
      { return lhs.y < rhs.y; }
    };

    struct CmpZ {
      bool operator() (const vec& lhs, const vec& rhs) const 
      { return lhs.z < rhs.z; }
    };

    template <typename T>
    bool chained(const T &, const T &) {
      return false;
    }

    template <typename CMP, typename T, typename ...P>
    bool chained(const T &t1, const T &t2, const CMP &c, P...p) {
      if (c(t1,t2)) { return true;          }
      if (c(t2,t1)) { return false;         }
      else          { return chained(t1, t2, p...); }
    }

    int main(int argc, char **argv) {
      vec x = { 1,2,3 }, y = { 2,2,3 }, z = { 1,3,3 };
      cout << chained(x,x,CmpX(),CmpY(),CmpZ()) << endl;
      return 0;
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top