【问题标题】:sorting std vector of strings without using default algorithm在不使用默认算法的情况下对字符串的标准向量进行排序
【发布时间】:2014-03-04 17:57:03
【问题描述】:

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

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

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

【问题讨论】:

  • 您可以简单地将它们重命名为'_%04d'
  • 编写自己的比较器函子并将其传递给排序?
  • 为什么without using default algorithm?什么default algorithm
  • 查看以下答案以获取参考。
  • @Manu343726:这根本不是重复的......它需要对正在排序的结构中的特定字段进行正常的“

标签: c++ sorting std


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      #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 &lt; rhs,则返回负数,如果相等则返回0,如果lhs &gt; rhs,则返回正数。

      您可以从指定给std::sort 的比较函子或lambda 调用它。

      【讨论】:

        【解决方案4】:

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

        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

        【讨论】:

          猜你喜欢
          • 2017-10-14
          • 1970-01-01
          • 1970-01-01
          • 2011-07-19
          • 1970-01-01
          • 2012-04-16
          • 2020-06-19
          • 2015-08-22
          • 2013-04-06
          相关资源
          最近更新 更多