2011-09-13 18 views
8

Destek kütüphanesini kullanarak, zip iterator kullanarak bilinen sayıda yineleyiciyi bir araya getirmek mümkündür, ancak çalışma zamanına kadar sıkıştırılacak yineleyici sayısı bilinmiyorsa ne olur?Zip Çeşitli Yineleyiciler C++ 'da

Biraz genişletmek için, aynı boyutta olan bir liste listem var ve her dizindeki tüm değerleri bir arada gruplandırmalı ve bunları başka bir işlemle beslemeliyim. Şu anda tüm bunlar manuel ve daha iyi bir yol olmalı diye düşünüyorum.

Örnek:

  • [1, 2, 3, 4, 5]
  • [11, 12, 13, 14, 15]
  • :

    I 3 listeleri vardır ki

  • [21, 22, 23, 24, 25] ben bu listeler dönüştürmek için gereken

:

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

Çalışma zamanına kadar girişte kaç tane liste bulunduğunu bilmiyorum.

+2

. Bir problemi çözmeye çalışıyorum * bunu anladığımı varsayarak, beni biraz sinirlendirir! – Nawaz

+3

@Nawaz: Bu bizi de tedirgin ediyor! –

+0

Bu, bir _matrix rotation_'a çok benziyor. Bunun için mevcut adaptörler olduğunu düşünmeyin. – MSalters

cevap

4

Neredeyse 1/2 saat harcadıktan sonra, STL benzeri yineleyiciler gibi görünmesi için daha da geliştirilebilecek olan bu dynamic_zip_iterator sınıfı ile geldim.

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

onu kullanma:

Neyse ona bir göz var,: Sana std::vector ile değiştirebilir ve hatta daha genel yapabileceğiniz içinde std::list kodlanmış ettik Bugün itibarıyla, bu çok özel olduğunu

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

Testi kodu:

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; 
} 
senin sorunun bu fonksiyona azaltır 210

Çıktı:

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

Çevrimiçi demo: Sana ne yapmak istediğini anlıyorum, ama sen ne yapmak istediğinizi anlatan bazı kod sonrası eğer daha iyi olurdu * düşünüyorum * http://ideone.com/3FJu1

2

Bunun için bugün hiçbir şey olmadığından eminim. Fakat neden yineleyici elemanların çok basit bir listesini oluşturmuyorsunuz? Bu hile yapardı, eminim! sonu,

artırmaz> başlaması, Ve bu yeterli olmalı -

for açıklamada her 3 parçaları için bir işlev oluşturun! Aşağıda biraz daha detay var.

  • başlar: -: (const ref listelemek için (const ref listeleri, Yineleyicilerin boş liste referans listesine)> her bir alt liste için()

  • ucu başlar kullanılarak yineleyici listesini oluşturmak iterators, listelerin liste const ref) arasında -> bir yineleyici listede sonunda eğer doğruysa

  • artışı: yineleyicileri listesine (ref) -> listesinde artış her yineleyici

+1

Bu, tüm yineleyicilerin aynı türde olması koşuluyla çalışmalıdır. Zip_iterator, yineleyici bir yineleyici ile çalıştığı ve bir tuple ilişkin kendi dereferanslarıyla çalıştığı için, her yineleyicinin türü ve onun referans_tipi farklı olabilir: bu tip bilgisi zip_iterator türüne aktarılır. Çalışma zamanı tarafından belirlenen yineleyici sayısı açıkça yineleyicinin türüne aktarılamaz ve çeşitli referans türleri de kullanılamaz. Ama hepsi aynıysa ve derleme zamanında biliniyorlarsa, sorun yok. –

+0

@Steve Jessop: Anladığım kadarıyla, anladım ki, Chris bir liste listesinden bahsediyorsa, tüm yineleyicilerin aynı türden olacağına dair bir tartışma yoktur. –