2011-09-13 36 views
8

Sử dụng thư viện tăng có thể nén cùng một số vòng lặp đã biết bằng cách sử dụng zip iterator, nhưng điều gì sẽ xảy ra khi số vòng lặp được nén không được biết cho đến khi chạy?Zip Một số Iterator trong C++

Để mở rộng một chút, tôi có danh sách các danh sách có cùng kích thước và tôi cần nhóm tất cả các giá trị tại mỗi chỉ mục và đưa chúng vào một thao tác khác. Ngay bây giờ đây là tất cả các hướng dẫn sử dụng, và tôi cảm thấy như có nên có một cách tốt hơn.

Ví dụ:

Nói rằng tôi có 3 danh sách:

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

tôi cần phải chuyển đổi các danh sách này vào:

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

Tôi không biết có bao nhiêu danh sách ở đầu vào cho đến khi chạy.

+2

* Tôi nghĩ * Tôi hiểu những gì bạn muốn làm, nhưng nó sẽ là tốt hơn nếu bạn gửi một số mã, mô tả những gì bạn muốn làm. Cố gắng giải quyết một vấn đề * giả sử * rằng tôi hiểu nó, làm cho tôi đôi khi lo lắng! – Nawaz

+3

@Nawaz: Nó cũng khiến chúng tôi lo lắng! –

+0

Điều này trông rất giống với vòng xoay _matrix_. Đừng nghĩ rằng có sẵn adapter cho điều đó. – MSalters

Trả lời

4

Được rồi sau khi chi tiêu gần 1/2 giờ, tôi đã bắt đầu với lớp học dynamic_zip_iterator này có thể được cải thiện hơn nữa, để làm cho nó trông giống như các trình vòng lặp giống như STL.Tính đến bây giờ, nó rất cụ thể, như tôi đã hardcoded std::list trong nó mà bạn có thể thay thế với std::vector hoặc có thể làm cho ngay cả chung chung hơn:

Dù sao, có một cái nhìn vào nó:

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

Sử dụng nó vấn đề của bạn làm giảm chức năng này: mã

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

Test:

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

Output:

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

bản demo online: http://ideone.com/3FJu1

2

Tôi khá chắc chắn không có gì tồn tại ngày hôm nay cho điều đó. Nhưng tại sao không tạo ra một danh sách rất đơn giản của các yếu tố lặp? Điều đó sẽ làm điều này, tôi chắc chắn!

Tạo một chức năng cho tất cả 3 phần của báo cáo kết quả for -> bắt đầu, kết thúc, tăng

Và đó nên là đủ! Chi tiết hơn một chút bên dưới.

  • bắt đầu: (ref const vào danh sách của danh sách, tài liệu tham khảo danh sách sản phẩm nào của vòng lặp) -> xây dựng danh sách iterator sử dụng bắt đầu() cho mỗi sublist

  • cuối: (ref const vào danh sách của vòng lặp, const ref vào danh sách của danh sách) -> đúng nếu một iterator là ở phần cuối của danh sách

  • increment: (ref vào danh sách của vòng lặp) -> tăng mỗi iterator trong danh sách

+1

Điều này sẽ hoạt động với điều kiện là tất cả các trình lặp có cùng loại. Vì 'zip_iterator' làm việc với một bộ các trình vòng lặp và các tham chiếu đến một bộ tuple, kiểu của mỗi trình lặp và tham chiếu của nó có thể khác nhau: thông tin kiểu đó được cuộn vào loại của trình nén zip_iterator. Một số vòng lặp xác định thời gian chạy được xác định rõ ràng không thể được cuộn vào loại của trình vòng lặp, cũng như không thể các loại tham chiếu khác nhau. Nhưng nếu tất cả chúng đều giống nhau và được biết đến ở thời gian biên dịch, không có vấn đề gì. –

+0

@Steve Jessop: Tôi hiểu ý của bạn, nhưng cho rằng Chris đề cập đến một danh sách các danh sách, không có tranh luận rằng tất cả các vòng lặp sẽ có cùng loại. –

Các vấn đề liên quan