2011-09-13 48 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提到了列表清單,沒有人爭論說所有的迭代器都具有相同的類型。 –