在不使用默认算法的情况下对字符串的 std 向量进行排序

sorting std vector of strings without using default algorithm

本文关键字:std 字符串 向量 排序 情况下 默认 算法      更新时间:2023-10-16

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

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

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

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

现在只需构造该二进制函数即可。这里有一个部分示例:对包含数字的 std::字符串进行排序?

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

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

下面是处理字符串中嵌入的任意数量的数值的比较:

#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 调用它。

您可以有一个自定义比较器,如下所示:

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) ;
    }
};

在此处观看演示