2011-09-13 47 views
8

使用boost库可以使用zip iterator将已知数量的迭代器压缩在一起,但是直到运行时才能知道要压缩的迭代器的数量?使用C++编写几个迭代器

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

说我有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]
  • ...等

直到运行时,我都不知道输入中有多少个列表。

+2

*我觉得*我明白你想要做什么,但如果你发布一些代码,描述你想要做什么会更好。试着解决一个问题*假设我明白了这一点,这让我有些紧张! – Nawaz

+3

@Nawaz:它也让我们紧张! –

+0

这看起来很像_matrix rotation_。不要以为现在有适配器。 – MSalters

回答

4

花了差不多1/2小时后,我想出了这个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

2

我很确定今天没有任何东西存在。但为什么不创建一个非常简单的迭代器元素列表?这将做到这一点,我相信!

所有3个部分for语句创建一个功能 - >开始,结束,增加

这应该是足够了!下面更详细一点。

  • 开始:(const的裁判列表,参照迭代的空列表的列表) - >构建体使用开始()为每个子列表

  • 端迭代列表:(常量REF列出迭代器,常量裁判名单的清单) - >如果真的一个迭代器在其列表的末尾

  • 增量:(裁判迭代器的列表) - >增量列表中的每个迭代

+1

只要所有的迭代器具有相同的类型,这应该工作。由于'zip_iterator'与迭代器的元组一起工作,并且自身对元组进行解引用,所以每个迭代器的类型和它的reference_type可以不同:该类型信息被卷入zip_iterator的类型中。显然不能将运行时确定的迭代器数量放入迭代器的类型中,也不能将各种引用类型放入迭代器的类型中。但是,如果它们在编译时都是一样的,并且没有问题。 –

+0

@Steve Jessop:我理解你的观点,但是鉴于Chris提到了列表清单,没有人争论说所有的迭代器都具有相同的类型。 –