2011-09-13 18 views
8

ブーストライブラリを使用すると、zip iteratorを使用して既知の反復子をまとめて圧縮することはできますが、実行時までZIPされるイテレータの数がわからないときはどうなりますか?Zip C++の複数の反復子

少し拡大すると、リストのリストはすべて同じサイズで、各インデックスごとにすべての値をグループ化し、別の操作にフィードする必要があります。今、これはすべてマニュアルです。より良い方法があるはずです。

  • [1、2、3、4、5]
  • [11、12、13、14、15]
  • はI 3つのリストを持っていると言います

  • 私はにこれらのリストを変換する必要がある[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

ほとんどの時間を費やした後、私はこのdynamic_zip_iteratorクラスを思いつきました。このクラスは、STLライクなイテレータのように見えるように、さらに改良することができます。

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::vectorに置き換えることができ、あるいはより一般的にすることができたことでstd::listをハードコードてきたように今のところ、それは、非常に具体的です

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; 
} 
あなたの問題は、この関数に減少し210

出力:

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

オンラインデモ:私は私はあなたが何をしたいのかを理解し、しかし、あなたは何をしたいのか説明し、いくつかのコードを投稿した場合、それは良いだろう*だと思う* http://ideone.com/3FJu1

2

私はそれのために今日は何も存在しないと確信しています。しかし、イテレータ要素の非常に単純なリストを作成してみませんか?それはトリックを行うだろう、私は確信しています!

for文のすべての3部のための関数を作成します - >、、エンドを開始

をインクリメントそして、それは十分なはずです!以下にもう少し詳しく説明します。

  • が開始:(リストのリストへのconst REF、イテレータの空のリストへの参照) - >(開始使用イテレータリストを構築する)各サブリスト

  • 端用:リストに(CONST REFイテレータ、リストのリストへのconst参照)の - > 1つのイテレータは、そのリストの最後にある場合はtrue

  • 増分:イテレータのリストへ(REF) - >リストの増分すべてのイテレータ

+1

これは、すべてのイテレータが同じ型であれば機能します。 'zip_iterator'はイテレータのタプルで動作し、それ自体がタプルに逆参照されるので、各イテレータとそのreference_typeの型は異なっていてもよい。型情報はzip_iteratorの型に丸められる。実行時に決定されるイテレータの数は、明らかにイテレータの型に転記することはできませんし、さまざまな参照型を使用することもできません。しかし、コンパイル時にそれらがすべて同じで既知であれば、問題はありません。 –

+0

@ Steve Jessop:私はあなたのことを理解していますが、Chrisがリストのリストを挙げると、すべてのイテレーターが同じタイプを持つとは言いません。 –