2011-09-13 24 views
8

Utilizzando la libreria boost è possibile comprimere un numero noto di iteratori utilizzando uno zip iterator, ma che dire quando il numero di iteratori da zippare non è noto fino al runtime?Zip Diversi iteratori in C++

Per espandere un po ', ho una lista di liste che sono tutte della stessa dimensione, e ho bisogno di raggruppare tutti i valori di ogni indice e dar loro da mangiare in un'altra operazione. In questo momento tutto questo è manuale, e sento che dovrebbe esserci un modo migliore.

Esempio:

Say Ho 3 elenca:

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

ho bisogno di trasformare queste liste in:

0.123.516,41 mila
  • [1, 11, 12]
  • [2, 12, 22]
  • [3, 13, 23]
  • [4, 14, 24]
  • ... ecc

Non so quante liste sono nell'input fino al runtime.

+2

* penso * Capisco quello che vuoi fare, ma sarebbe meglio se si posta un codice, descrivendo ciò che si vuole fare. Cercando di risolvere un problema * assumendo * che lo capisco, mi rende un po 'nervoso! – Nawaz

+3

@Nawaz: Ci rende nervosi anche noi! –

+0

Sembra molto simile a _matrix rotation_. Non pensare che ci siano adattatori esistenti per questo. – MSalters

risposta

4

OK. Dopo aver trascorso quasi mezz'ora, ho trovato questa classe dynamic_zip_iterator che può essere ulteriormente migliorata, per farla sembrare come iteratori simili a STL.A partire da ora, è molto specifica, come ho hardcoded std::list in esso, che è possibile sostituire con std::vector o può rendere ancora più generico:

In ogni caso, date un'occhiata a questo articolo:

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

Usandolo il problema si riduce a questa funzione: codice

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

prova:

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

uscita:

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

Demo in linea: http://ideone.com/3FJu1

2

Sono abbastanza sicuro che nulla esiste oggi per quello. Ma perché non creare un elenco molto semplice di elementi iteratori? Quello sarebbe il trucco, ne sono sicuro!

creare una funzione per tutte le 3 parti della dichiarazione for -> inizio, fine, incrementa

E questo dovrebbe essere sufficiente! Un po 'più in dettaglio qui sotto.

  • iniziare: (ref const all'elenco di liste, riferimento all'elenco vuoto di iteratori) -> costruire l'elenco iteratore utilizzando cominciare() per ogni sottolista

  • fine: (ref const alla lista di iteratori, ref const alla lista di liste) -> vero se si iteratore è alla fine della sua lista

  • minimo: (ref alla lista dei iteratori) -> incremento ogni iteratore nella lista

+1

Questo dovrebbe funzionare a condizione che tutti gli iteratori abbiano lo stesso tipo. Dato che 'zip_iterator' funziona con una tupla di iteratori, e se stessa dereferenzia ad una tupla, il tipo di ciascun iteratore e il suo tipo_di_referenza possono essere diversi: quel tipo di informazione è arrotolata nel tipo di zip_iterator. Ovviamente un numero determinato di iteratori determinati dal runtime non può essere inserito nel tipo di iteratore, né i diversi tipi di riferimento. Ma se sono tutti uguali e conosciuti al momento della compilazione, nessun problema. –

+0

@Steve Jessop: Capisco il tuo punto, ma dato che Chris menziona un elenco di elenchi, non si può sostenere che tutti gli iteratori avranno lo stesso tipo. –