2014-10-18 101 views
3

这是我一直在考虑的事情。我已经做了一些研究,找不到任何东西,但我还没有发现任何相反的事情。是否有可能使用std :: sort与带额外参数的排序函数?

请考虑<algorithm>中的std::sort函数。它需要两个迭代器和一个函数指针作为参数。所以,如果我想按字母顺序排序字符串矢量,我会做这样的事情:

bool ascending(std::string lhs, std::string rhs) { return lhs < rhs; } 

std::sort(my_vector.begin(), my_vector.end(), ascending); 

的事情是,这种类型的排序功能是区分大小写的,所以才会将一个字符串以小写开头“一'以大写字母'Z'开始的字符串之后。我看到的唯一可见的解决方案是沿着bool ascending_case_insensitive()的线创建附加功能。不过,如果我可以在排序中使用bool ascending()函数并附加bool is_case_sensitive参数,那将会很不错。这可能吗?

+1

这需要绑定函子/ lambda – deviantfan 2014-10-18 20:27:39

+0

C++ 11或C++ 03? – 2014-10-18 20:27:40

+0

11非常好。 – 2014-10-18 20:28:09

回答

12

如果你现在有

bool ascending(std::string lhs, std::string rhs); 

std::sort(my_vector.begin(), my_vector.end(), ascending); 

你可以有

bool ascending(std::string lhs, std::string rhs, bool case_sensitive); 

using namespace std::placeholders; 
std::sort(my_vector.begin(), my_vector.end(), std::bind(ascending, _1, _2, false)); 

std::bind点是返回调用时,一个对象,调用绑定的功能,可选改变了论据。您可以使用它来更改参数顺序,添加可选参数或将参数设置为特定的固定值。

+0

'绑定'是跛脚。使用lambdas。而且,AFAICS这个解决方案将会遇到性能问题(不仅仅是因为'bind'),不是吗? – Columbo 2014-10-18 20:44:45

+2

@Loopunroller如果你想编写更多的代码来达到相同的结果,当然,去做吧,但是当有一个标准的库函数做我想要的,那么我没有理由不使用它。我不确定你指的是什么性能问题,所以我既不能确认也不否认这些问题是真实的。 – hvd 2014-10-18 20:47:05

+0

进行了一些测量后,您的代码看起来似乎只有一小部分,比如1.1。我很抱歉。 – Columbo 2014-10-18 21:05:03

4

由于std::sort需要比较函子的一个实例,因此您可以使用参数给函数的构造函数确定其行为。例如,

class StringCompare 
{ 
public: 
StringCompare(bool is_case_sensitive=true) : is_case_sensitive(is_case_sensitive){} 
bool operator()(const string&, const string&);///This would handle the comparison using the is_case_sensitive flag 
private: 
bool is_case_sensitive; 
}; 

std::sort(my_vector.begin(), my_vector.end(), StringCompare(true));//case-sensitive comparison 
std::sort(my_vector.begin(), my_vector.end(), StringCompare(false));//case-insensitive comparison 
+0

Upvoting提供一种与C++ 03一起使用的方法。可悲的是,并非我们所有人都在使用C++ 11或更高版本,并有权访问std :: bind()。 – GuyGizmo 2016-05-03 22:16:59

1

有如下,包括函数调用与绑定额外的参数,并通过价值捕获额外的参数lambda表达式的例子:

#include <iostream>// for std::cout 
#include <vector>// for std::vector 
#include <functional> // for std::bind 
#include <algorithm> // for std::sort 

bool ltMod(int i, int j, int iMod) { 
    return (i % iMod) < (j % iMod); 
} 

int main() { 
    std::vector<int> v = {3,2,5,1,4}; 
    int iMod = 4; 

    std::cout << "\nExample for the usage of std::bind: "; 
    // _1 and _2 stand for the two arguments of the relation iMod is the bound parameter 
    std::sort(v.begin(),v.end(),std::bind(ltMod,std::placeholders::_1,std::placeholders::_2,iMod)); 

    for(auto i : v) std::cout << i << ','; 

    iMod = 3; 

    std::cout << "\nExample for lambda: "; 
    // lambdas are unnamed inplace functions 
    // iMod is captured by value. You can use the value within the function. 
    std::sort(v.begin(),v.end(),[iMod](int i, int j){ return ltMod(i,j,iMod); }); 
    for(auto i : v) std::cout << i << ','; 

    return 0; 
} 
/** 
    Local Variables: 
    compile-command: "g++ -std=c++11 test.cc -o a.exe" 
    End: 
*/ 
0

以为我会回答我的问题,以总结我得到的回应。所以从我所收集的内容来看,我基本上有两种选择。

第一个将写一个lambda函数来处理我的一次性案例。

// Lambda solution. 
std::sort(my_vector.begin(), my_vector.end(), 
    [](std::string const &lhs, std::string const &rhs) // Thanks for optimizing my example code guys. No, seriously. ;) 
    { 
     return boost::toupper(lhs) < boost::toupper(rhs); 
    }); 

第二个更可重用的选项是创建一个仿函数来处理这些排序情况。

// Functor solution. 
class SortAscending 
{ 
private: 
    bool _is_case_sensitive; 
public: 
    SortAscending(bool is_case_sensitive) : 
     _is_case_sensitive(is_case_sensitive); 

    bool operator()(std::string const &lhs, std::string const &rhs) 
    { 
     if (_is_case_sensitive) 
      return boost::toupper(lhs) < boost::toupper(rhs); 
     else 
      return lhs < rhs; 
    } 
}; 

std::sort(my_vector.begin(), my_vector.end(), SortAscending(false)); 

那么认为这几乎总结了我的选择?

相关问题