如何从 std::map 检索所有键(或值)并将它们放入向量中?
这是我得出的可能方法之一:
struct RetrieveKey
{
template <typename T>
typename T::first_type operator()(T keyValuePair) const
{
return keyValuePair.first;
}
};
map<int, int> m;
vector<int> keys;
// Retrieve all keys
transform(m.begin(), m.end(), back_inserter(keys), RetrieveKey());
// Dump all keys
copy(keys.begin(), keys.end(), ostream_iterator<int>(cout, "\n"));
当然,我们也可以通过定义另一个函子RetrieveValues来从地图中检索所有值。
还有其他方法可以轻松实现这一目标吗? (我总是想知道为什么 std::map 不包含我们这样做的成员函数。)
This is one of the possible ways I come out:
struct RetrieveKey
{
template <typename T>
typename T::first_type operator()(T keyValuePair) const
{
return keyValuePair.first;
}
};
map<int, int> m;
vector<int> keys;
// Retrieve all keys
transform(m.begin(), m.end(), back_inserter(keys), RetrieveKey());
// Dump all keys
copy(keys.begin(), keys.end(), ostream_iterator<int>(cout, "\n"));
Of course, we can also retrieve all values from the map by defining another functor RetrieveValues.
Is there any other way to achieve this easily? (I'm always wondering why std::map
does not include a member function for us to do so.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(25)
使用 C++20 的另一种方法
范围库有一个键视图,它检索类似对/元组类型中的第一个元素:
值得一提的两个相关视图:
Yet Another Way using C++20
The ranges library has a keys view, which retrieves the first element in a pair/tuple-like type:
Two related views worth mentioning:
有一个 用于此目的的 boost 范围适配器:
有一个类似的 map_values 范围适配器用于提取值。
There is a boost range adaptor for this purpose:
There is a similar map_values range adaptor for extracting the values.
C++0x 给了我们一个进一步的、优秀的解决方案:
C++0x has given us a further, excellent solution:
基于 @rusty-parks 解决方案,但在 c++17 中:
Based on @rusty-parks solution, but in c++17:
@DanDan 的答案,使用 C++11 是:
使用 C++14(如 @ivan.ukr 所指出的),我们可以将
decltype(map_in)::value_type
替换为auto
代码>.@DanDan's answer, using C++11 is:
and using C++14 (as noted by @ivan.ukr) we can replace
decltype(map_in)::value_type
withauto
.您的解决方案很好,但您可以使用迭代器来执行此操作:
Your solution is fine but you can use an iterator to do it:
SGI STL 有一个名为
select1st
的扩展。 可惜它不是标准 STL 格式!The SGI STL has an extension called
select1st
. Too bad it's not in standard STL!使用结构化绑定(“解构”)声明语法 C++17的,
可以这样做,比较容易理解。
With the structured binding (“destructuring”) declaration syntax of C++17,
you can do this, which is easier to understand.
我认为上面介绍的 BOOST_FOREACH 很好而且很干净,但是,还有另一个使用 BOOST 的选项。
就我个人而言,我认为这种方法在这种情况下不如 BOOST_FOREACH 方法那么干净,但 boost::lambda 在其他情况下可以非常干净。
I think the BOOST_FOREACH presented above is nice and clean, however, there is another option using BOOST as well.
Personally, I don't think this approach is as clean as the BOOST_FOREACH approach in this case, but boost::lambda can be really clean in other cases.
c++11 的一些内容:
Bit of a c++11 take:
这是一个使用 C++11 魔法的漂亮函数模板,适用于 std::map、std::unordered_map:
在这里查看: http://ideone.com/lYBzpL
Here's a nice function template using C++11 magic, working for both std::map, std::unordered_map:
Check it out here: http://ideone.com/lYBzpL
另外,如果您有 Boost,请使用transform_iterator 以避免制作键的临时副本。
Also, if you have Boost, use transform_iterator to avoid making a temporary copy of the keys.
可以像这样使用 std::ranges::copy
在 C++20 中使用范围,如果您想要值而不是键
并且不喜欢管道语法,则
Using ranges in C++20 you can use std::ranges::copy like this
if you want values instead of keys
and if you don't like the pipe syntax
您可以使用多功能的 boost::transform_iterator。 Transform_iterator 允许您转换迭代值,例如在我们的例子中,您只想处理键,而不是值。 请参阅http://www.boost.org/ doc/libs/1_36_0/libs/iterator/doc/transform_iterator.html#example
You can use the versatile boost::transform_iterator. The transform_iterator allows you to transform the iterated values, for example in our case when you want to deal only with the keys, not the values. See http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/transform_iterator.html#example
最好的非 sgi、非 boost STL 解决方案是像这样扩展 map::iterator ,
然后像这样使用它们:
The best non-sgi, non-boost STL solution is to extend map::iterator like so:
and then use them like so:
我发现以下三行代码是最简单的方法:
它是这个答案第一种方法的缩短版本。
I found the following three lines of code as the easiest way:
It is a shorten version of the first way of this answer.
以下函子检索映射的键集:
Bonus:以下函子检索映射的值集:
用法:
预期输出:
The following functor retrieves the key set of a map:
Bonus: The following functors retrieve the value set of a map:
Usage:
Expected output:
借助 Eric Niebler 的 range-v3 库,您可以使用
ranges::to
获取一个范围并将其直接写入容器(希望很快会在std
中实现,也许是 C++ 26?):[演示]
With Eric Niebler's range-v3 library, you can take a range and write it out directly to a container using
ranges::to
(hopefully soon instd
, maybe C++26?):[Demo]
迄今为止最简洁的解决方案,使用 C++23:
请参阅编译器资源管理器中的实时示例。
这使用新的
std::vector
构造函数 将std::from_range_t
作为以及std::views::keys
和std::views::values
来自<范围>
。The cleanest solution yet, using C++23:
See live example at Compiler Explorer.
This uses the new
std::vector
constructor takingstd::from_range_t
, as well asstd::views::keys
andstd::views::values
from<ranges>
.以原子图为例
With atomic map example
您可以使用 fplus 库 中的 get_map_keys() :
You can use get_map_keys() from fplus library:
与此处的示例之一略有相似,从
std::map
使用角度进行了简化。像这样使用:
Slightly similar to one of examples here, simplified from
std::map
usage perspective.Use like this:
因为它不能比你做得更好。 如果方法的实现并不优于自由函数的实现,那么通常您不应该编写方法; 你应该写一个自由函数。
目前还不清楚为什么它有用。
Because it can't do it any better than you can do it. If a method's implementation will be no superior to a free function's implementation then in general you should not write a method; you should write a free function.
It's also not immediately clear why it's useful anyway.
虽然您的解决方案应该有效,但根据其他程序员的技能水平,它可能很难阅读。 此外,它将功能从调用站点移开。 这会使维护变得更加困难。
我不确定你的目标是将密钥放入向量中还是将它们打印出来,所以我两者都做。 您可以尝试这样的操作:
或者甚至更简单,如果您使用 Boost 库: 就
我个人而言,我喜欢 BOOST_FOREACH 版本,因为打字更少,而且它的作用非常明确。
While your solution should work, it can be difficult to read depending on the skill level of your fellow programmers. Additionally, it moves functionality away from the call site. Which can make maintenance a little more difficult.
I'm not sure if your goal is to get the keys into a vector or print them to cout so I'm doing both. You may try something like this:
Or even simpler, if you are using the Boost library:
Personally, I like the BOOST_FOREACH version because there is less typing and it is very explicit about what it is doing.