簡體   English   中英

將幾個 std::list 迭代器壓縮在一起

[英]Zip several std::list iterators together

使用 boost 庫,可以使用zip iterator將已知數量的迭代器壓縮在一起,但是當要壓縮的迭代器數量直到運行時才知道時怎么辦?

為了稍微擴展一下,我有一個大小相同的列表列表,我需要將每個索引處的所有值組合在一起,並將它們提供給另一個操作。 現在這都是手動的,我覺得應該有更好的方法。

示例

假設我有 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]
  • ... 等等

直到運行時,我才知道輸入中有多少個列表。

好吧,在花了將近 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

我很確定今天沒有任何東西存在。 但是為什么不創建一個非常簡單的迭代器元素列表呢? 那會奏效的,我敢肯定!

for語句的所有 3 個部分創建一個函數 --> begin, end, increment

這應該足夠了! 下面詳細介紹一下。

  • begin : (const ref to list of list, reference to empty list of iterators) --> 使用 begin() 為每個子列表構造迭代器列表

  • end : (const ref to list of iterators, const ref to list of lists) --> 如果一個迭代器在其列表的末尾,則為真

  • increment : (ref to list of iterators) --> 增加列表中的每個迭代器

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM