在C ++中压缩几个迭代器

时间:2011-09-13 15:32:14

标签: c++ iterator

使用boost库可以使用zip iterator将已知数量的迭代器压缩在一起,但是什么时候直到运行时才能知道要压缩的迭代器数量?

为了扩展一点,我有一个大小相同的列表列表,我需要将每个索引的所有值组合在一起并将它们提供给另一个操作。现在这都是手动的,我觉得应该有更好的方法。

实施例

说我有3个名单:

  • [1,2,3,4,5]
  • [11,12,13,14,15]
  • [21,22,23,24,25]

我需要将这些列表转换为:

  • [1,11,12]
  • [2,12,22]
  • [3,13,23]
  • [4,14,24]
  • ...... etc

我不知道在运行时输入中有多少列表。

2 个答案:

答案 0 :(得分:4)

好好花了将近半小时后,我想出了这个可以进一步改进的dynamic_zip_iterator类,使其看起来像STL类似的迭代器。截至目前,它非常具体,因为我已经在其中加密std::list,您可以用std::vector替换它,或者可以更加通用:

无论如何,看看它:

template<typename T>
struct dynamic_zip_iterator
{
   typedef typename std::list<T>::iterator list_iterator;
   std::list<list_iterator> iterators;
   std::list<std::list<T>> * plists;
   dynamic_zip_iterator(std::list<std::list<T>> & lists, bool isbegin) : plists(&lists) 
   {
         auto it = plists->begin();
         for( ; it != plists->end(); ++it)
         {
           if ( isbegin )
                iterators.push_back(it->begin()); 
           else
                iterators.push_back(it->end()); 
         }
   }
   dynamic_zip_iterator(const dynamic_zip_iterator & zip) : 
          plists(zip.plists),iterators(zip.iterators) {}

   dynamic_zip_iterator operator++()
   { 
     auto it = iterators.begin();
     for( ; it != iterators.end(); ++it)
          ++(*it);
     return *this;
   }
   std::list<T> operator*() 
   { 
     std::list<T> lst;
     auto it = iterators.begin();
     for( ; it != iterators.end(); ++it)
          lst.push_back(*(*it));     
     return lst;
   }
   bool operator!=(dynamic_zip_iterator &zip)
   { 
     auto it1 = iterators.begin();
     auto it2 = zip.iterators.begin();
     return (*it1) != (*it2);
   }
   static dynamic_zip_iterator begin(std::list<std::list<T>> & lists)
   {
      return dynamic_zip_iterator<T>(lists, true);
   }
   static dynamic_zip_iterator end(std::list<std::list<T>> & lists)
   {
      return dynamic_zip_iterator<T>(lists, false);
   }
};

使用它可以减少您的问题:

std::list<std::list<int>> create_lists(std::list<std::list<int>>& lists)
{
  std::list<std::list<int>> results;
  auto begin = dynamic_zip_iterator<int>::begin(lists);
  auto end = dynamic_zip_iterator<int>::end(lists);
  for( ; begin != end ; ++begin)
  {
     results.push_back(*begin);
  }
  return results;    
}

测试代码:

int main() {
        int a[] = {1, 2, 3, 4, 5}, b[] = {11, 12, 13, 14, 15}, c[] = {21, 22, 23, 24, 25};
        std::list<int> l1(a,a+5), l2(b,b+5), l3(c,c+5);
        std::list<std::list<int>> lists;
        lists.push_back(l1); 
        lists.push_back(l2);
        lists.push_back(l3);
        std::list<std::list<int>> newlists = create_lists(lists);
        for(auto lst = newlists.begin(); lst != newlists.end(); ++lst)
        {
                std::cout << "[";
                std::copy(lst->begin(), lst->end(), std::ostream_iterator<int>(std::cout, " "));
                std::cout << "]" << std::endl;
        }
        return 0;
}

输出:

[1 11 21 ]
[2 12 22 ]
[3 13 23 ]
[4 14 24 ]
[5 15 25 ]

在线演示:http://ideone.com/3FJu1

答案 1 :(得分:2)

我很确定今天没有任何东西存在。但是为什么不创建一个非常简单的迭代元素列表呢?我确定,那就行了!

for语句的所有3个部分创建一个函数 - &gt;开始,结束,增量

这应该够了!下面详细介绍一下。

  • begin :( const ref到列表列表,对空迭代器列表的引用) - &gt;使用begin()为每个子列表

  • 构造迭代器列表
  • end :( const ref到迭代器列表,const ref到列表列表) - &gt;如果一个迭代器位于其列表的末尾,则为true

  • increment :(参考迭代器列表) - &gt;递增列表中的每个迭代器