سؤال

أقوم بفرز السلاسل التي تتكون من نص وأرقام.أريد أن يقوم الفرز بفرز أجزاء الأرقام كأرقام، وليس أبجدية رقمية.

مثلا أريد:abc1def، ...، abc9def، abc10def

بدلاً من:abc10def، abc1def، ...، abc9def

هل يعرف أحد خوارزمية لهذا (خاصة في c++)

شكرًا

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

المحلول

انا سألت هذا السؤال بالضبط (على الرغم من وجوده في Java) وتمت الإشارة إليه http://www.davekoelle.com/alphanum.html الذي يحتوي على خوارزمية وتطبيقات لها بالعديد من اللغات.

نصائح أخرى

وهذا هو المعروف باسم الفرز الطبيعي. هناك خوارزمية هنا أن تبدو واعدة.

كن حذرا من المشاكل مع أحرف غير ASCII (انظر جيف بلوق على موضوع دخول).

تتوفر العديد من تطبيقات الفرز الطبيعي لـ C++.استعراض موجز:

  • natural_sort<> - على أساس Boost.Regex.
    • في اختباراتي، كان أبطأ بحوالي 20 مرة من الخيارات الأخرى.
  • ديرك جاغدمان alnum.hpp, ، بناءً على ديف كويل خوارزمية الأبجدية
    • يتغلب العدد الصحيح المحتمل على مشكلات القيم التي تتجاوز MAXINT
  • مارتن بول natsort - مكتوب بلغة C، ولكن يمكن استخدامه بشكل تافه من C++.
    • تطبيق C/C++ الوحيد الذي رأيته يقدم إصدارًا غير حساس لحالة الأحرف، والذي يبدو أنه يمثل أولوية عالية للنوع "الطبيعي".
    • مثل التطبيقات الأخرى، فهو لا يقوم في الواقع بتحليل النقاط العشرية، ولكنه يقوم بتحليل الأصفار البادئة في حالة خاصة (أي شيء به 0 يُفترض أنه كسر)، وهو أمر غريب بعض الشيء ولكنه قد يكون مفيدًا.
    • يستخدم PHP هذه الخوارزمية.

جوابي آخر :

bool compareNat(const std::string& a, const std::string& b){
    if (a.empty())
        return true;
    if (b.empty())
        return false;
    if (std::isdigit(a[0]) && !std::isdigit(b[0]))
        return true;
    if (!std::isdigit(a[0]) && std::isdigit(b[0]))
        return false;
    if (!std::isdigit(a[0]) && !std::isdigit(b[0]))
    {
        if (a[0] == b[0])
            return compareNat(a.substr(1), b.substr(1));
        return (toUpper(a) < toUpper(b));
        //toUpper() is a function to convert a std::string to uppercase.
    }

    // Both strings begin with digit --> parse both numbers
    std::istringstream issa(a);
    std::istringstream issb(b);
    int ia, ib;
    issa >> ia;
    issb >> ib;
    if (ia != ib)
        return ia < ib;

    // Numbers are the same --> remove numbers and recurse
    std::string anew, bnew;
    std::getline(issa, anew);
    std::getline(issb, bnew);
    return (compareNat(anew, bnew));
}

وظيفة toUpper():

std::string toUpper(std::string s){
    for(int i=0;i<(int)s.length();i++){s[i]=toupper(s[i]);}
    return s;
    }

والاستعمال:

std::vector<std::string> str;
str.push_back("abc1def");
str.push_back("abc10def");
...
std::sort(str.begin(), str.end(), compareNat);

لحل ما هي في جوهرها مشكلة التوزيع على جهاز الدولة (ويعرف أيضا باسم محدود دولة إنسان ) هو الطريق للذهاب. غير راضين عن الحلول السابقة كتبت واحدة تمر في وقت مبكر إنقاذ خوارزمية بسيطة أن يدق C / C ++ المتغيرات المقترحة أعلاه من حيث الأداء، لا يعاني من الأخطاء نوع البيانات تجاوز العددية، وسهلة لتعديل لإضافة حالة عدم الاكتراث إذا لزم الأمر .

ويمكن العثور على مصادر href="https://www.o-rho.com/naturalsort" هنا

// -1: s0 < s1; 0: s0 == s1; 1: s0 > s1
static int numericCompare(const string &s0, const string &s1) {
    size_t i = 0, j = 0;
    for (; i < s0.size() && j < s1.size();) {
        string t0(1, s0[i++]);
        while (i < s0.size() && !(isdigit(t0[0]) ^ isdigit(s0[i]))) {
            t0.push_back(s0[i++]);
        }
        string t1(1, s1[j++]);
        while (j < s1.size() && !(isdigit(t1[0]) ^ isdigit(s1[j]))) {
            t1.push_back(s1[j++]);
        }
        if (isdigit(t0[0]) && isdigit(t1[0])) {
            size_t p0 = t0.find_first_not_of('0');
            size_t p1 = t1.find_first_not_of('0');
            t0 = p0 == string::npos ? "" : t0.substr(p0);
            t1 = p1 == string::npos ? "" : t1.substr(p1);
            if (t0.size() != t1.size()) {
                return t0.size() < t1.size() ? -1 : 1;
            }
        }
        if (t0 != t1) {
            return t0 < t1 ? -1 : 1;
        }
    }
    return i == s0.size() && j == s1.size() ? 0 : i != s0.size() ? 1 : -1;
}

وأنا لست متأكدا جدا اذا كانت تريد، على أي حال، هل يمكن أن يكون المحاولة: -)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top