如果我有一个容器(vector
,list
等),其中每个元素都是std::pair
,是否有一种简单的方法可以迭代每对元素的每个元素?
即。
std::vector<std::pair<int,int> > a;
a.push_back(std::pair(1,3));
a.push_back(std::pair(2,3));
a.push_back(std::pair(4,2));
a.push_back(std::pair(5,2));
a.push_back(std::pair(1,5));
然后能够迭代该值:1,3,2,3,4,2,5,2,1,5?
类似地,什么类型的仿函数/函数会返回一个容器(相同类型),并且具有上述对元素的平面列表?
答案 0 :(得分:7)
首先,您必须创建自己的迭代器类,该类将指示内部对位置的标志与container<pair>
迭代器
对于第二种,它更容易,虽然要像你想要的那样一般(相同类型的容器),你需要template typedef。这里只是矢量:
template <class V>
std::vector<V> flatten_pairs(std::vector<std::pair<V,V> > const& a) {
typedef std::vector<std::pair<V,V> > A;
std::vector<V> ret;
for (typename A::const_iterator i=a.begin(),e=a.end();i!=e;++i) {
ret.push_back(i->first);
ret.push_back(i->second);
}
return ret;
}
以下是伪造模板typedef的方法:
template <class C>
struct same_container;
template <class V>
struct same_container<std::vector<V> > {
template <class W> struct rebind { typedef std::vector<W> type; };
};
template <class V>
struct same_list<std::list<V> > {
template <class W> struct rebind { typedef std::list<W> type; };
};
template <class C>
typename same_container<C>::rebind<typename C::value_type::first_type>::type
flatten_pairs(C const& a);
答案 1 :(得分:5)
以下代码将根据需要打印所有值:
for ( size_t x = 0; x < a.size(); ++x ) {
cout << a[x].first << "," << a[x].second << ",";
}
我更喜欢这种方法,而不是创建自定义迭代器。
答案 2 :(得分:3)
要将容器的容器展平成第二个容器,您也可以简单地编写自己的插件:
template<class C>
struct Inserter {
std::back_insert_iterator<C> in;
Inserter(C& c) : in(c) {}
void operator()(const std::pair<typename C::value_type, typename C::value_type>& p)
{
*in++ = p.first;
*in++ = p.second;
}
};
template<class C>
Inserter<C> make_inserter(C& c)
{
return Inserter<C>(c);
}
// usage example:
std::list<int> l;
std::for_each(a.begin(), a.end(), make_inserter(l));
答案 3 :(得分:1)
没有简单的方法来执行你想要的迭代,但你可能想看看boost :: iterator_adaptor库或实现你自己的迭代器来做它(它不应该太复杂)。然后,在第二个问题上,您可以将std :: copy与新的迭代器适配器一起使用。
答案 4 :(得分:1)
不,std::pair
确实没有这样的事情。您可能需要考虑使用Boost Tuple。元组有点像std::pair
的扩展版本,它允许任意数量的元素(达到某个限制,但通常至少为10),并且还可以访问元素(如向量/数组)(即您可以通过名称或索引访问元素。
TR1还包括std :: tr1 :: tuple,它是Boost元组的一个子集,但是如果内存服务,它仍然包含你要求的名称/索引功能。
编辑:请注意,在这两种情况下,索引表示法都需要索引的编译时常量,因此您无法编写(运行时)循环来迭代元素中的元素一个元组 - 但你可以通过一些元编程来完成这项工作。 Boost融合包括相当多的支持你需要的东西(通过一些奇怪的巧合,元组是融合库的一部分)。
答案 5 :(得分:0)
在某些时候,您需要使用 first 和 second ,即使您创建自己的迭代器类也是如此。我认为没有办法摆脱它(至少,以便携方式)。