我的std::map
有一对'唯一键'和'唯一值'。我通常会找到一个值的键,并为键找到一个值。
我已经知道使用std::find_if
+ lambda的方法,但是我想知道是否有更好的方法。
搜索之后,我找到了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 更快。 这是测试结果控制台。
所以,我的问题是,
find_if
+ lambda是最好的方法吗?
(不幸的是,我不能使用boost库。)std::binary_function
?感谢您抽出时间查看此主题并尝试提供帮助。
答案 0 :(得分:1)
假设您具有透明比较的C ++ 1y功能,您可以创建std::set
std::map::iterator
.second
按.second
字段排序,并使比较器透明,以便您可以通过std::map
字段的类型在其中进行查找。
但这不太可能。
如果你没有这个,并且你可以使你的值字段(合理地)便宜复制,你可以从值字段到迭代器的std::unordered_map
或std::map
到{{1 }}。假设您需要在主地图中同时查找和顺序。
如果您不需要订购,请停止使用map
:
typedef std::unordered_map< int, std::string > main_map;
typedef std::unordered_map< std::string, int > backwards_map;
然后将上面的内容包装在一些样板中以保持两者同步。
请注意unordered_map
迭代器是非持久的。 std::map
迭代器是高度持久的。因此,对于双unordered
案例,向后地图是不同的。
对于binary_function
和bind2nd
,不推荐使用。
答案 1 :(得分:1)
在我的情况下(我的意思是按值搜索地图),find_if + lambda是最好的方法吗?
这当然是最好的方式(假设您不能使用第二张地图,或者可能是升压式多索引地图,以快速查找值)。原则上,使用等效仿函数和/或bind
不应该明显更慢,这里唯一的区别是nick_name
是通过值而不是引用来捕获的;也许您还没有启用优化,或者您的编译器可能没有优化bind2nd
以及人们可能希望的优化。
当我使用
时std::binary_function
?
从历史上看,如果您不想自己定义别名,那么您将继承它以将类型别名(first_argument_type
,second_argument_type
和result_type
)注入您的仿函数中。这些有时是必需的,例如当使用bind2nd
之类的适配器(也已弃用)来创建基于您的函数的新仿函数。
我知道在C ++ 11中,
std::binary_function
已被弃用。我能知道原因吗?
它定义的类型对于bind
这样的新式可变参数适配器既不必要也不够,所以它不再有用了。