给定一个multimap<A,B> M,用一个特定的键创建一个包含M中所有值的vector<B>的简洁方法是什么?例如,给定一个multimap,我如何得到所有Map到值123的字符串的向量?
multimap<A,B>
vector<B>
dwbf0jvd1#
下面是STL风格的实现方法:
// The following define is needed for select2nd with DinkumWare STL under VC++ #define _HAS_TRADITIONAL_STL 1 #include <algorithm> #include <vector> #include <map> #include <string> #include <functional> #include <map> #include <iterator> #include <iostream> using namespace std; void main() { typedef multimap<string, int> MapType; MapType m; vector<int> v; // Test data for(int i = 0; i < 10; ++i) { m.insert(make_pair("123", i * 2)); m.insert(make_pair("12", i)); } MapType::iterator i = m.lower_bound("123"); MapType::iterator j = m.upper_bound("123"); transform(i, j, back_inserter(v), select2nd<MapType::value_type>()); copy(v.begin(), v.end(), ostream_iterator<int>(cout, ",")); }
7jmck4yq2#
让我们用lambda
给定:multimap<A,B> Mrequested:vector<B>(M中所有值的一个特定键'a'。方法:
multimap<A,B> M
std::pair<M::iterator, M::iterator> aRange = M.equal_range('a') std::vector<B> aVector; std::transform(aRange.first, aRange.second,std::back_inserter(aVector), [](std::pair<A,B> element){return element.second;});
系统环境:1.编译器:gcc(Ubuntu 5.3.1-14ubuntu2.1)5.3.1 20160413(with -std=c++11)1.操作系统:ubuntu 16.04代码示例:
#include <algorithm> #include <vector> #include <map> #include <string> #include <functional> #include <iostream> int main() { typedef std::multimap<std::string, int> MapType; MapType m; std::vector<int> v; /// Test data for(int i = 0; i < 10; ++i) { m.insert(std::make_pair("123", i * 2)); m.insert(std::make_pair("12", i)); } std::pair<MapType::iterator,MapType::iterator> aRange = m.equal_range("123"); std::transform(aRange.first, aRange.second, std::back_inserter(v), [](std::pair<std::string,int> element){return element.second;}); for(auto & elem: v) { std::cout << elem << std::endl; } return 0; }
l2osamch3#
反正你需要一个循环。所有的“无循环”方法都只是将循环抽象出来。
#include <map> #include <vector> #include <algorithm> #include <ext/functional> using namespace std; int main () { multimap<int, double> mm; mm.insert(make_pair(1, 2.2)); mm.insert(make_pair(4, 2.6)); mm.insert(make_pair(1, 9.1)); mm.insert(make_pair(1, 3.1)); vector<double> v; transform(mm.lower_bound(1), mm.upper_bound(1), back_inserter(v), __gnu_cxx::select2nd<pair<int, double> >()); // note: select2nd is an SGI extension. for (vector<double>::const_iterator cit = v.begin(); cit != v.end(); ++ cit) printf("%g, ", *cit); // verify that you've got 2.2, 9.1, 3.1 return 0; }
yzxexxkh4#
template <class Key, class Val> vector<Val>& getValues(multimap<Key, Val>& multi, Key& key) { typedef multimap<Key, Val>::iterator imm; static vector<Val> vect; static struct { void operator()(const pair<Key, Val>& p) const { vect.push_back(p.second); } } Push; vect.clear(); pair<imm, imm> range = multi.equal_range(key); for_each(range.first, range.second, Push); return vect; }
这是一个有点做作,因为你的'无循环'的要求。我更喜欢:
template <class Key, class Val> vector<Val> getValues(multimap<Key, Val>& map, Key& key) { vector<Val> result; typedef multimap<Key, Val>::iterator imm; pair<imm, imm> range = map.equal_range(key); for (imm i = range.first; i != range.second; ++i) result.push_back(i->second); return result; }
4ioopgfo5#
你可以通过给它两个迭代器来初始化向量,像这样:
std::multimap<std::string, std::string> bar; ... std::vector<pair<string,string> > foo(bar.lower_bound("123"), bar.upper_bound("123"));
但这将给予你一个向量对(即,与键和值)。另一种选择是使用std::copy和类似back_inserter的东西,这是另一种隐藏循环的方法,但缺点与上面相同。
std::copy
std::copy(bar.lower_bound("123"), bar.upper_bound("123"), std::back_inserter(foo));
这将把元素(如果有的话)附加到向量foo。对于只提取值,我想不出任何方法,但循环结果,因为我不知道一个标准的方法来获得一个范围外的值。
erhoui1w6#
只是对其他答案的一些补充...std::mem_fn(来自#include <functional>)可以用作变换运算符的简写:
std::mem_fn
#include <functional>
// previously we might've used this longhand [](pair<int,string> element){return element.second;}
我们可以使用vector::resize和std::distance一次性为向量分配空间,而不是使用back_inserter重复调整大小。
vector::resize
std::distance
#include <algorithm> #include <vector> #include <map> #include <string> #include <functional> #include <iterator> #include <iostream> using namespace std; typedef multimap<int, string> MapType; int main() { MapType multimap; vector<string> valuesForKey123; multimap.emplace(0, "red"); multimap.emplace(123, "hello"); multimap.emplace(123, "world"); multimap.emplace(0, "herring"); MapType::iterator lower{multimap.lower_bound(123)}; MapType::iterator upper{multimap.upper_bound(123)}; valuesForKey123.resize(distance(lower, upper)); transform( lower, upper, valuesForKey123.begin(), mem_fn(&MapType::value_type::second)); copy( valuesForKey123.begin(), valuesForKey123.end(), ostream_iterator<string>(cout, " ")); } // outputs "hello world "
jq6vz3qz7#
为了得到匹配的元素,我们可以使用equal_range。在Map中,每个元素都是一对。在这种情况下,我们不能直接使用STL copy算法将匹配的元素复制到向量中,因为我们没有直接复制元素(对),所以我们希望本质上执行“Map”操作(使用函数式编程中的map/filter术语),在C++中我们可以使用transform算法来执行:
equal_range
copy
transform
#include <iostream> #include <map> // for multimap #include <vector> #include <algorithm> // for transform using namespace std; int main() { multimap<int, string> m = { {1, "a"}, {1, "b"}, {123, "c"}, {123, "d"}, {2, "e"} }; vector<string> v; auto [begin, end] = m.equal_range(123); transform(begin, end, back_inserter(v), [](const pair<int, string>& p) { return p.second; }); cout << "v: "; for (auto& x : v) cout << x << " "; }
输出:
v: c d
7条答案
按热度按时间dwbf0jvd1#
下面是STL风格的实现方法:
7jmck4yq2#
让我们用lambda
给定:
multimap<A,B> M
requested:
vector<B>
(M中所有值的一个特定键'a'。方法:
系统环境:
1.编译器:gcc(Ubuntu 5.3.1-14ubuntu2.1)5.3.1 20160413(with -std=c++11)
1.操作系统:ubuntu 16.04
代码示例:
l2osamch3#
反正你需要一个循环。所有的“无循环”方法都只是将循环抽象出来。
yzxexxkh4#
这是一个有点做作,因为你的'无循环'的要求。
我更喜欢:
4ioopgfo5#
你可以通过给它两个迭代器来初始化向量,像这样:
但这将给予你一个向量对(即,与键和值)。
另一种选择是使用
std::copy
和类似back_inserter的东西,这是另一种隐藏循环的方法,但缺点与上面相同。这将把元素(如果有的话)附加到向量foo。
对于只提取值,我想不出任何方法,但循环结果,因为我不知道一个标准的方法来获得一个范围外的值。
erhoui1w6#
只是对其他答案的一些补充...
std::mem_fn
(来自#include <functional>
)可以用作变换运算符的简写:我们可以使用
vector::resize
和std::distance
一次性为向量分配空间,而不是使用back_inserter重复调整大小。jq6vz3qz7#
为了得到匹配的元素,我们可以使用
equal_range
。在Map中,每个元素都是一对。在这种情况下,我们不能直接使用STL
copy
算法将匹配的元素复制到向量中,因为我们没有直接复制元素(对),所以我们希望本质上执行“Map”操作(使用函数式编程中的map/filter术语),在C++中我们可以使用transform
算法来执行:输出: