2014-10-18 67 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)); 

那麼認爲這幾乎總結了我的選擇?

相關問題