How to retrieve all keys (or values) from a std::map and put them into a vector?涵盖了从C ++ 11之前的地图中的键填充std :: vector的方法。
有没有办法在C ++ 11中使用lambdas等执行此操作,这意味着我们可以在一行中执行此操作,以便我们可以从地图初始化向量而不是创建向量并在2个操作中填充它?
e.g。 vector<int> v(???(m.begin(),m.end()));
纯C ++ 11是首选,但提升是可以接受的...目的是在一行中完成此操作而不会过于复杂并且#34;炫耀&#34;,所以它不会混淆给其他开发者。
为了比较&#34;显而易见的&#34; C ++ 11解决方案是:
vector<int> v;
v.reserve(m.size()); //not always needed
for(auto &x : map)
v.push_back(x.first)
答案 0 :(得分:4)
在Boost.Range中使用boost::adaptor::map_keys
。
#include <iostream>
#include <vector>
#include <map>
#include <boost/range/adaptor/map.hpp>
int main()
{
const std::map<int, std::string> m = {
{1, "Alice"},
{2, "Bob"},
{3, "Carol"}
};
auto key_range = m | boost::adaptors::map_keys;
const std::vector<int> v(key_range.begin(), key_range.end());
for (int x : v) {
std::cout << x << std::endl;
}
}
输出:
1
2
3
答案 1 :(得分:4)
你去,C ++ 11 one-liner:)
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <iterator>
int main(int, char**)
{
std::map<int, std::string> map {
{1, "one"},
{2, "two"},
{3, "three"}
};
std::vector<int> keys;
// Reserve enough space (constant-time)
keys.reserve(map.size());
// Retrieve the keys and store them into the vector
std::transform(map.begin(), map.end(), std::back_inserter(keys),
[](decltype(map)::value_type const &pair) {return pair.first;}
);// ^^^^^^^^^^^^^^^^^^^^^^^^^ Will benefit from C++14's auto lambdas
// Display the vector
std::copy(keys.begin(), keys.end(),
std::ostream_iterator<int>(std::cout, " "));
return 0;
}
std::transform
非常强大。
答案 2 :(得分:2)
如下所示:
#include <vector>
#include <map>
#include <boost/iterator/transform_iterator.hpp>
int main() {
std::map<std::string, int> m{{"abc", 1}, {"def", 2}};
auto extractor = [](decltype(m)::value_type const& kv) { return kv.first; };
std::vector<std::string> v(
boost::make_transform_iterator(m.begin(), extractor)
, boost::make_transform_iterator(m.end(), extractor)
);
}
请注意,与使用vector
或vector
填充它的向量的解决方案相比,将迭代器传递给push_back
的构造函数是初始化resize
的最有效方法默认值首先。
答案 3 :(得分:2)
没有,使用任何std::vector
构造函数重载,在一行中的纯C ++ 11中无法做到这一点,没有例如创建自己的迭代器适配器。
在两个行中做的很简单,例如:
std::vector<Key> v;
for (const auto& p : m) v.push_back(p.first);
为此目的创建自己的迭代器适配器也很容易,例如:
template <typename InputIt>
struct key_it : public InputIt {
key_it(InputIt it) : InputIt(it) {}
auto operator*() { return (*this)->first; }
};
// Helper function for automatic deduction of iterator type.
template <typename InputIt>
key_it<InputIt> key_adapt(InputIt it) {
return {it};
}
现在,您可以使用以下命令在一行中创建和填充std::vector
std::vector<Key> v{key_adapt(std::begin(m)), key_adapt(std::end(m))};
答案 4 :(得分:1)
略微改进Quentin's solution:
std::vector<int> keys(map.size());
transform(map.begin(), map.end(), keys.begin(),
[](std::pair<int, std::string> const &p) { return p.first; });
或更可读:
std::vector<int> keys(map.size());
auto get_key = [](std::pair<int, std::string> const &p) { return p.first; };
transform(map.begin(), map.end(), keys.begin(), get_key);
可能更好:
int get_key(std::pair<int, std::string> const &p) { return p.first; }
std::vector<int> get_keys(const std::map<int, std::string> &map)
{
std::vector<int> keys(map.size());
transform(map.begin(), map.end(), keys.begin(), get_key);
return keys;
}
然后打电话:
std::vector<int> keys = get_keys(map);
如果要使用很多。
答案 5 :(得分:0)
std::vector
类有两个相关的构造函数:
vector(std::initializer_list<T>)
[C ++ 11] vector(InputIterator first, InputIterator last)
[C ++ 98] 第一个是新的C ++ 11构造函数,它允许您执行以下操作:
std::vector<int> v{ 1, 2, 3 };
第二个允许你做的事情:
std::vector<int> w{ v.rbegin(), v.rend() }; // 3, 2, 1
我没有看到使用initializer_list
构造函数的方法(因为你没有预先提供这些项目),所以你最好的选择是创建一个{{1适用于key_iterator
并返回std::map<T, K>::iterator
而不是(*i).first
的类。例如:
(*i)
这还要求您编写std::vector<int> keys{ key_iterator(m.begin()), key_iterator(m.end()) };
类,您可以使用Boost迭代器适配器来简化任务。使用2行版本可能更容易。
答案 6 :(得分:0)
Whoopse,我意识到这实际上并没有回答你的问题(必须学会正确阅读)!
我可能会这样做:
#include <map>
#include <vector>
#include <iostream>
int main()
{
std::map<int, std::string> m =
{
{1, "A"}, {2, "B"}, {3, "C"}
};
std::vector<int> v;
v.reserve(m.size());
for(auto&& i: m)
v.emplace_back(i.first);
for(auto&& i: v)
std::cout << i << '\n';
}