【问题标题】:Sort C++ Strings with multiple criteria使用多个条件对 C++ 字符串进行排序
【发布时间】:2011-03-10 17:45:53
【问题描述】:

我需要对 C++ std::vector<std::string> fileNames 进行排序。文件名是这样标记的

YYDDDTTTT_Z_SITE

YY = 年(即 2009 = 09、2010 = 10) DDD = 一年中的某一天(即 1 月 1 日 = 001,12 月 31 日 = 365) TTTT = 一天中的时间(即午夜 = 0000,中午 = 1200)

ZONE = 将是 E 或 W

SITE = 四个字母的网站名称(即 HILL、SAMM)

我需要按以下顺序对字符串进行排序:ZONE、SITE、YY、DDD、TTTT

【问题讨论】:

    标签: c++ string sorting vector


    【解决方案1】:

    std::sort 与比较函数一起使用。

    (链接有一个很好的例子)

    【讨论】:

      【解决方案2】:

      简单的部分:编写排序本身:

      // Return true if the first arg is strictly less than the second
      bool compareFilenames(const std::string& rhs, const std::string& lhs);
      ...
      std::sort(fileNames.begin(), fileNames.end(), &compareFilenames);
      

      更难的部分:编写比较本身。在伪代码中,为了全面起见:

      bool compareFilenames(const std::string& lhs, const std::string& rhs)
      {
          parse the filenames
          if (lhs zone != rhs zone)
              return lhs zone < rhs zone
          if (lhs site != rhs site)
              return lhs site < rhs site
          ...
          return false
      }
      

      其中lhs site 等是您需要排序的各个数据位,从文件名中挑选出来。

      但是,鉴于您拥有严格的文件命名结构以及您的特定排序需求,您实际上可以通过第一个 '_' 字符拆分字符串并对第二个块进行字典顺序比较,然后是第一个如果第二个块相等,则为块。这将使解析文件名的代码更容易,但如果文件命名格式发生变化,则可能会降低灵活性。

      【讨论】:

        【解决方案3】:

        只需编写一个方法,根据您的标准比较两个文件名,以确定哪个文件名先出现,然后使用任何标准排序方法。

        【讨论】:

          【解决方案4】:

          使用std::sort 并实现一个比较类

          查看http://www.cplusplus.com/reference/stl/list/sort/了解更多详情

          【讨论】:

            【解决方案5】:

            您传递给vector::sort() 的排序谓词可能会创建重新排序的临时字符串,然后进行比较。

            【讨论】:

              【解决方案6】:

              您可以将qsort 与您自己的字符串比较函数一起使用,该函数会考虑您的排序规则以及每个向量中请求数组的第一个元素的地址。
              http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/

              但你不应该。只需使用std::sort

              【讨论】:

              • 投反对票。 Qsort 对一个容器的内容进行排序?你一定是疯了。
              • AFAIK,向量保证将其内容存储在内存中的连续数组中。只需传递第一个元素的地址。不过,您是对的,可能没有理由使用std::sort 这样做。
              • 我确定这不是错误的,但是 qsort 不安全或次优是否有实际原因?我想知道。
              • @user379118: 第一,如果可以内联比较函数,std::sort 可能工作得更快。您可以搜索基准或自己做。第二,有些人非常害怕在 C++ 中使用指针。第三,qsort 实际上可能比其他排序算法效率低,具体取决于环境和数据。插入排序在部分排序的数据上的工作速度甚至比 qsort 更快。不过,这取决于数据的大小和数组中未排序数据的数量。只要您正确实现了 qsort 的比较例程,它就会起作用。
              • @user379118:“qsort 不安全或次优是否有实际原因?” qsort 将使用 memcpy 或等效的东西复制对象。这仅支持 POD(“plain old data”)类型;粗略地说,基本类型和简单结构,但不是任何具有非平凡构造函数、析构函数或赋值运算符的东西。 std::string 不是 POD,因此使用 qsort 对它们进行排序会产生未定义的行为。同样std::sort 可以内联比较,而qsort 每次都必须调用一个函数(通过指针),所以std::sort 可以快很多。
              【解决方案7】:

              这是一个 boost lambda 函数版本。这是矫枉过正,而且非常神秘,但就如何处理不同的领域标准而言,它是简短而灵活的。显然你需要提升。此外,预计会增加编译时间。所以,这里是:

              #include <boost/lambda/lambda.hpp>
              #include <boost/lambda/bind.hpp>
              #include "boost/lambda/detail/operator_actions.hpp"
              #include "boost/lambda/detail/operator_return_type_traits.hpp"
              #include "boost/lambda/detail/control_structures_impl.hpp"
              #include "boost/ref.hpp"
              #include <iostream>
              #include <vector>
              #include <string>
              #include <iterator>
              #include <algorithm>
              #include <cassert>
              
              using namespace std;
              using namespace boost::lambda;
              
              //helpers: a better way would be to group them
              //under a flyweight, or something...
              string extract_year(string str_)
              {
                  return str_.substr(0,2);
              }
              
              string extract_dayofyear(string str_)
              {
                  return str_.substr(2,3);
              }
              
              string extract_timeofday(string str_)
              {
                  return str_.substr(5,4);
              }
              
              string extract_zone(string str_)
              {
                  return str_.substr(10,1);
              }
              
              string extract_site(string str_)
              {
                  return str_.substr(12,4);
              }
              
              //Uhm, just for brevity... ('cause otherwise we should stay away from macros ;-)
              #define IF_THEN_ELSE_RET(op1,op2,exp) if_then_else_return(var(op1)<var(op2),true,if_then_else_return(var(op1)>var(op2),false,exp))
              
              void sort_fnames(vector<string>& fnames)
              {
                  string z1,z2,s1,s2,y1,y2,d1,d2,t1,t2;
              
                  //sort by zone-then-site-then-year-then-day-then-time:
                  //Note the format of the sort(fnames.begin(),fnames.end(), (,...,boolean_expression) );
                  //remember, in a sequence of comma-dellimited statements enclosed between parens, like
                  //val=(.,...,boolean_expression); only the last expression, boolean_expression, gets
                  //assigned to variable "val";
                  //So, in the sort() call below, the statements 
                  //var(z1)=bind(extract_zone,_1),var(z2)=bind(extract_zone,_2), etc.
                  //are only initializing variables that are to be used in the composition 
                  //of if_then_else_return(,,) lambda expressions whose composition 
                  //combines the zone-then-site-then-year-then-day-then-time criteria 
                  //and amounts to a boolean that is used by sort to decide the ordering
                  sort(fnames.begin(),fnames.end(),
                      (var(z1)=bind(extract_zone,_1),var(z2)=bind(extract_zone,_2),
                       var(s1)=bind(extract_site,_1),var(s2)=bind(extract_site,_2),
                       var(y1)=bind(extract_year,_1),var(y2)=bind(extract_year,_2),
                       var(d1)=bind(extract_dayofyear,_1),var(d2)=bind(extract_dayofyear,_2),
                       var(t1)=bind(extract_timeofday,_1),var(t2)=bind(extract_timeofday,_2),
                       IF_THEN_ELSE_RET(z1,z2,IF_THEN_ELSE_RET(s1,s2,IF_THEN_ELSE_RET(y1,y2,IF_THEN_ELSE_RET(d1,d2,IF_THEN_ELSE_RET(t1,t2,true)))))
                       ));
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2020-06-02
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-03-10
                • 2021-11-09
                • 2010-12-20
                • 2012-02-24
                相关资源
                最近更新 更多