将多个std::list迭代器压缩在一起
Zip several std::list iterators together
使用boost库可以使用zip迭代器将已知数量的迭代器压缩到一起,但是当要压缩的迭代器数量直到运行时才知道时该怎么办?
稍微扩展一下,我有一个列表的列表,这些列表的大小都相同,我需要将每个索引处的所有值组合在一起,并将它们提供给另一个操作。现在这些都是手动的,我觉得应该有更好的方法。
示例:
假设我有3个列表:
- [1,2,3,4,5]
- [11, 12, 13, 14, 15]
- [21, 22, 23, 24, 25]
我需要把这些列表转换成:
- [1,1,12]
- [2, 12, 22]
- [3,13,23]
- [4,14,24]
- …等
直到运行时我才知道输入中有多少个列表
好了,在花了将近一个半小时之后,我想出了这个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 lists, reference to empty list of iterator)——>为每个子列表使用begin()构造迭代器列表
-
end: (const ref to list of iterators, const ref to list of lists)——>如果一个迭代器位于其列表的末尾
-
increment: (ref to list of iterators)——>对列表中的每个迭代器进行递增
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 跟随整数索引列表的自定义类迭代器
- 不明白迭代器,引用和指针失效,一个例子
- 我可以使用反向迭代器作为ForwardIt吗
- ESP8266单片机矢量迭代器的C++问题
- 如何在C++中将迭代器作为函数参数传递
- 是否应避免从非常量迭代器转换为常量迭代器?
- 如何在 c++ 中将字符串迭代器变量传递给函数?
- 为什么 vector 的随机访问迭代器给出与指针不同的内存地址?
- 将多个std::list迭代器压缩在一起