不使用默认算法排序字符串的std向量

时间:2014-03-04 17:57:03

标签: c++ sorting std

我有std::vector std::strings,每个都是文件名。假设文件名的格式为some_name_n.xyz

问题是some_name_10.xyz小于some_name_2.xyz。这些文件是由其他一些进程生成的。

对它们进行排序的最不痛苦的方法是什么,以便'_'之后的数字被考虑进行比较,而不仅仅是它的长度?

4 个答案:

答案 0 :(得分:1)

最不痛苦的方法是将适当的前导零放入文件名中(即使编写第二个脚本来获取生成的名称并重命名它们可能比编写自己的排序例程更容易。)

第二种最不痛苦的方法是编写自己的排序谓词,将_分隔数字排序为数字而不是按字典顺序排列。

答案 1 :(得分:1)

std::sort允许您指定二进制函数来比较两个元素:http://www.cplusplus.com/reference/algorithm/sort/

现在只需构建二进制函数即可。这里有一个部分示例:Sorting std::strings with numbers in them?

答案 2 :(得分:1)

这是一个比较,它处理字符串中嵌入的任意数量的数值:

#include <cstdlib>
#include <cctype>
#include <iostream>

#ifdef  _MSC_VER
#define strtoll _strtoi64
#endif

int cmp(const char* lhs, const char* rhs)
{
    while (*lhs || *rhs)
    {
        if (isdigit(*lhs) && isdigit(*rhs))
        {
            char* l_end;
            char* r_end;
            long long l = strtoll(lhs, &l_end, 10);
            long long r = strtoll(rhs, &r_end, 10);
            if (l < r) return -1;
            if (l > r) return 1;
            lhs = l_end;
            rhs = r_end;
        }
        else
            if (*lhs != *rhs)
                return *lhs - *rhs;
            else
                ++lhs, ++rhs;
    }
    return *lhs - *rhs;
}

故意“C风格”,因此它可以直接有效地应用于角色阵列。如果lhs < rhs则返回负数,如果相等则返回0,如果lhs > rhs则返回正数。

您可以从指定为std::sort的比较仿函数或lambda中调用它。

答案 3 :(得分:1)

您可以使用以下自定义比较器:

struct Comp{

    auto get_num (const std::string& a)
    {
        auto it1 = std::find_if( a.begin(), a.end(), ::isdigit );
        auto it2 = std::find_if( a.begin(), a.end(), 
                               [](char x){ return x == '.' ;}) ;
        /* Do some checks here for std::string::npos*/
        auto pos1 = std::distance( a.begin(), it1) ;
        auto pos2 = std::distance( it1, it2) ;
        return std::stoi (a.substr( pos1, pos2 )) ;
    }

    bool operator () (const std::string& a, const std::string& b)
    {
        return get_num (a) < get_num (b) ;
    }

};

请参阅演示here