2014-01-20 97 views
1

我的std::map有一對'唯一鍵'和'唯一值'。我通常找到一個關鍵值,並找到一個關鍵值。 我已經知道使用std::find_if + lambda的方法,但是我想知道是否有更好的方法。std :: find_if,std :: binary_function用於按值搜索std :: map

搜索後,我發現this article,我學會了如何使用`std :: binary_function'。 使用這兩種方法,我已經檢查'經過時間'。 這是我的代碼。

typedef int         USER_ID; 
typedef std::string       USER_NICK_NAME; 
typedef std::map<USER_ID, USER_NICK_NAME> USER_MAP; 

template<class T> 
struct map_data_compare : public std::binary_function<typename T::value_type, typename T::mapped_type, bool> 
{ 
    public: 
    bool operator() (typename T::value_type &pair, typename T::mapped_type i) const 
    { 
    return pair.second == i; 
    } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    USER_MAP user_map; 
    string nick_prefix = "test"; 

    //make test map 
    for (int i = 0; i < 100000; i++) 
    { 
    std::ostringstream stream; 
    stream << i; 
    user_map.insert(USER_MAP::value_type(i, nick_prefix + stream.str())); 
    } 

    const USER_NICK_NAME nick_name = "test99999"; 
    clock_t t; 

    //Method 1 : using find_if + lambda 
    cout << "Method 1 : using find_if + lambda" << endl; 
    t = clock(); 
    auto it = std::find_if(user_map.begin(), user_map.end(), [&](const USER_MAP::value_type& user) 
    { 
    return nick_name == user.second; 
    }); 
    if (it != user_map.end()) 
    { 
    cout << "found nickname " << nick_name.c_str() << ", at index " << it->first << endl; 
    } 
    t = clock() - t; 
    cout << "elapsed " << ((float)t)/CLOCKS_PER_SEC << " seconds" << endl; 

    cout << endl << endl; 

    //Method 2 : using find_if + binary_function 
    cout << "Method 2 : using using find_if + binary_function" << endl; 
    t = clock(); 
    it = std::find_if(user_map.begin(), user_map.end(), std::bind2nd(map_data_compare<USER_MAP>(), nick_name)); 
    if (it != user_map.end()) 
    { 
    cout << "found nickname " << nick_name.c_str() << ", at index " << it->first << endl; 
    } 
    t = clock() - t; 
    cout << "elapsed " << ((float)t)/CLOCKS_PER_SEC << " seconds" << endl; 

    return 0; 
} 

在我的機器,方法1總是快於方法2。 這是測試結果控制檯。 enter image description here

所以,我的問題是,

  1. 在我的情況(我的意思是通過搜索值映射),find_if +拉姆達是最好的方式? (遺憾的是,我無法使用增強庫。)
  2. 當我使用std::binary_function
  3. 我知道在C++ 11中,`std :: binary_function'已被棄用。我能知道原因嗎?

謝謝您的時間查看此主題並嘗試提供幫助。

+0

該和std :: bind2nd被棄用的原因是我們現在有'std :: function'和'std :: bind'的事實。 – chris

+0

你可以使用C++ 11而不是Boost?有趣的...... bimap對你來說是完美的。 –

+0

你有C++ 1y基於'set' /'map'的透明運算符嗎? – Yakk

回答

1

在我的情況下(我的意思是按值查找地圖),find_if + lambda是最好的方法嗎?

這當然是最好的方式(假設你不能使用第二張地圖,或者可能是一個助推式多指數地圖來快速查找值)。原則上,使用等效仿函數和/或bind應該不會明顯變慢,這裏唯一的區別是nick_name被值捕獲而不是參考;也許你還沒有啓用優化,或者你的編譯器不會像人們希望的那樣優化bind2nd

當我使用std::binary_function

歷史,你會從它繼承注入類型別名(first_argument_typesecond_argument_typeresult_type)到您的函子,如果你不喜歡自己定義它們。這些有時是必需的,例如當使用類似bind2nd的適配器(也被棄用)來創建一個基於你的函數的新函子時。

我知道在C++ 11中,std::binary_function已被棄用。我能知道原因嗎?

它定義的類型對於像bind這樣的新型可變參數適配器來說既不必要也不足夠,因此它不再有用。

+0

感謝您的回答。這對我很有幫助。正如你所說的,我禁用了「優化」。再次感謝你。 – hyun

1

假設你已經比較透明的C++ 1Y功能,您可以創建std::map::iterator一個由.second場排序的std::set,並進行比較透明,所以你可以通過.second的類型做它查找領域。

但這不太可能。

如果你沒有做到這一點,你可以讓你的值域(合理的)便宜複製,你可以做一個std::mapstd::unordered_map從值字段迭代器的std::map。這假設您需要在主映射中查找的順序。

如果你不需要命令,停止使用map

typedef std::unordered_map< int, std::string > main_map; 
typedef std::unordered_map< std::string, int > backwards_map; 

然後敷在上面一些樣板,以保持兩個同步。

請注意,unordered_map迭代器是非持久性的。迭代器是高度持久的。因此,雙向unordered情況下的向後地圖是不同的。

至於binary_functionbind2nd,它已被棄用。

+0

感謝您的回答。我不知道'透明比較',但我不能在'C++ 11 + VS2010'中使用它們。我對麼?再次感謝。 – hyun

+0

@CodeDreamer VS2013 alpha測試編譯器*可能*支持它。但是,不,2010年沒有。 – Yakk

+0

非常感謝。祝你今天愉快! – hyun