使用多个条件对C ++字符串进行排序

时间:2010-07-01 16:31:10

标签: c++ string sorting vector

我需要对C ++ std::vector<std::string> fileNames进行排序。 fileNames标记为

YYDDDTTTT_Z_SITE

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

ZONE =将是E或W

站点=四个字母的站点名称(即HILL,SAMM)

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

7 个答案:

答案 0 :(得分:7)

std::sort与比较功能结合使用。

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

答案 1 :(得分: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等是您需要排序的数据的各个位,从文件名中挑选出来。

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

使用std::sort并实施比较类

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

答案 4 :(得分:0)

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

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

即可

答案 5 :(得分:0)

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

答案 6 :(得分:0)

这是一个提升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)))))
         ));
}