迭代对容器中的对元素 (C++)

发布于 2024-08-13 18:42:45 字数 424 浏览 3 评论 0原文

如果我有一个容器(向量列表等),其中每个元素都是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?

同样,什么类型的函子/函数会返回给我一个容器(相同类型),其中包含上面的对元素的平面列表?

If I have a container (vector, list, etc) where each element is a std::pair, is there an easy way to iterate over each element of each pair?

i.e.

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));

and then being able to iterate over the value: 1,3,2,3,4,2,5,2,1,5?

Similarly, what type of functor/function would return to me a container (of the same type) with a flat listing of the pair elements as above?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

青瓷清茶倾城歌 2024-08-20 18:42:45

对于第一个,您必须创建自己的迭代器类,它将指示对内位置的标志与 container 迭代器配对。

对于第二个,它更容易,尽管与一般一样您想要(相同类型的容器)需要一个 模板 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);

For your first, you have to create your own iterator class, which pairs a flag indicating the within-pair position with a container<pair> iterator

For the second, it's easier, although to be as general as you want (container of same type) you need a template typedef. Here's for just vector:

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;
}

Here's how you fake a template 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);
莫相离 2024-08-20 18:42:45

以下代码将根据需要打印所有值:

for ( size_t x = 0; x < a.size(); ++x ) {
    cout << a[x].first << "," << a[x].second << ",";
}

与创建自定义迭代器相比,我更喜欢这种简单的方法。

The following code will print all values as required:

for ( size_t x = 0; x < a.size(); ++x ) {
    cout << a[x].first << "," << a[x].second << ",";
}

I'd prefer this easy way than creating custom iterator.

逐鹿 2024-08-20 18:42:45

要将成对的容器压平到第二个容器中,您也可以简单地编写自己的插入器:

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));

To flatten your container of pairs into a second container you could also simply write your own inserter:

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));
巴黎盛开的樱花 2024-08-20 18:42:45

没有简单的方法来执行您想要的迭代,但您可能需要查看 boost::iterator_adaptor 库或实现您自己的迭代器来执行此操作(它不应该太复杂)。然后,对于第二个问题,您可以将 std::copy 与新的迭代器适配器一起使用。

There is no simple way of performing the iteration you want, but you may want to take a look at the boost::iterator_adaptor library or implement your own iterator to do it (it should not be too complex). Then, on the second question, you can use std::copy with your new iterator adaptor.

喵星人汪星人 2024-08-20 18:42:45

不,std::pair 确实不存在这样的东西。您可能需要考虑使用 Boost Tuple。元组有点像 std::pair 的扩展版本,它允许任意数量的元素(最多一定限制,但通常至少 10 个),并提供对元素的访问,类似于向量/数组也是如此(即您可以通过名称或索引访问元素)。

TR1 还包括 std::tr1::tuple,它是 Boost 元组的子集,但如果没记错的话,它仍然包括您要求的名称/索引功能。

编辑:请注意,在这两种情况下,索引表示法都需要索引的编译时常量,因此您无法编写(运行时)循环来迭代元组中的元素 - - 但你可以通过一些元编程来完成这项工作。 Boost fusion 包含相当多的内容来支持您需要的内容(出于某种奇怪的巧合,元组是融合库的一部分)。

No, there really isn't such a thing for std::pair. You might want to consider using a Boost Tuple instead. A tuple is a bit like an expanded version of std::pair that allows an arbitrary number of elements (up to some limit, but normally at least 10), and gives access to the elements something like a vector/array as well (i.e. you can access the elements by either name or index).

TR1 also includes std::tr1::tuple, which is a subset of Boost's tuple, but if memory serves, it still includes the name/index functionality you're asking for.

Edit: note that in both cases, the index notation requires a compile-time constant for the index, so you can't write a (run-time) loop to iterate over the elements in a tuple -- but you can do the job with a bit of metaprogramming. Boost fusion includes quite a bit to support what you'd need (by some strange coincidence, tuple is part of the fusion library).

九厘米的零° 2024-08-20 18:42:45

有时您需要使用firstsecond,即使您创建了自己的迭代器类。我认为没有办法摆脱它(至少以可移植的方式)。

At some point you need to use first and second, even if you create your own iterator class. I don't think there's a way out of it (at least, in a portable manner).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文