How to implement a natural sort algorithm in c++?

后端 未结 8 1529
不思量自难忘°
不思量自难忘° 2020-11-30 10:21

I\'m sorting strings that are comprised of text and numbers. I want the sort to sort the number parts as numbers, not alphanumeric.

For example I want: abc1def, ...

8条回答
  •  粉色の甜心
    2020-11-30 10:37

    Partially reposting my another answer:

    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() function:

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

    Usage:

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

提交回复
热议问题