对带有数字的 std::strings 进行排序?

新手上路,请多包涵

我目前正在按 std::string < 运算符进行排序。它的问题在于:

30 < 9。由于 3 < 9,30 出现在 9 之前,Windows 9x 出现了这个问题。我怎样才能对它们进行数字排序,以便在“9 条狗”之后出现“30 只狐狸”。我还应该补充一点,我正在使用 utf 8 编码。

谢谢

原文由 jmasterx 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 597
1 个回答

您可以创建自定义比较函数以与 std::sort 一起使用。该函数必须检查字符串是否以数值开头。如果是这样,请使用字符串流等机制将每个字符串的数字部分转换为 int 。然后比较两个整数值。如果值比较相等,则按字典顺序比较字符串的非数字部分。否则,如果字符串不包含数字部分,只需按字典顺序正常比较两个字符串。

基本上,类似于以下(未经测试的)比较函数:

 bool is_not_digit(char c)
{
    return !std::isdigit(c);
}

bool numeric_string_compare(const std::string& s1, const std::string& s2)
{
    // handle empty strings...

    std::string::const_iterator it1 = s1.begin(), it2 = s2.begin();

    if (std::isdigit(s1[0]) && std::isdigit(s2[0])) {
        int n1, n2;
        std::stringstream ss(s1);
        ss >> n1;
        ss.clear();
        ss.str(s2);
        ss >> n2;

        if (n1 != n2) return n1 < n2;

        it1 = std::find_if(s1.begin(), s1.end(), is_not_digit);
        it2 = std::find_if(s2.begin(), s2.end(), is_not_digit);
    }

    return std::lexicographical_compare(it1, s1.end(), it2, s2.end());
}

接着…

 std::sort(string_array.begin(), string_array.end(), numeric_string_compare);

编辑:当然,此算法仅在您对数字部分出现在字符串开头的字符串进行排序时才有用。如果您正在处理数字部分可以出现在字符串中的 任何位置 的字符串,那么您需要一个更复杂的算法。有关详细信息,请参阅 http://www.davekoelle.com/alphanum.html

原文由 Charles Salvia 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题