我有一个包含涉及STL容器的嵌套遍历的代码。特别是我有一个顶级容器(列表),其中包含子列表,这些子列表包含更多子列表。对于例如在DICOM结构中,患者可以进行多项研究,每项研究可以有多个系列。我必须对Series对象执行一些操作,并且到达它们的唯一方法是深入循环,如下所示。
伪代码看起来像这样。
STLContainer top;
STLContainer::iterator top_iter;
for ( top_iter= top.begin(); top_iter != top.end(); ++top_iter) {
STLContainer mid = *top_iter;
STLContainer::iterator mid_iter;
for ( mid_iter = mid.begin(); mid_iter!= mid.end(); ++mid_iter) {
STLContainer bottom = *mid_iter;
STLContainer::iterator bottom_iter;
for(bottom_iter = bottom.begin(); bottom_iter != bottom.end(); ++bottom_iter){
ExecuteSomething(*bottom_iter); // Finally do something with the stored object
}
}
}
现在如果我必须在这些“底部”对象上重复执行一系列操作,我必须一次又一次地进行遍历。如果我想使用STL算法,我需要为每个嵌套级别写入至少3行“for_each”。
是否有人知道缩短此代码的技术可能会有点像这样?
// Drills down to the deepest nested container
for_each(top.begin(), top.end(), DrillDownAndExecuteOnBottom());
只能在一行中使用?像这样的东西? 谢谢!
答案 0 :(得分:3)
假设容器不是所有相同的元素类型:
struct DrillDownAndExecuteOnBottom
{
template<typename T>
void operator()(T& t) const
{ for_each(t.begin(), t.end(), *this); }
void operator()(Bottom& b) const
{ ExecuteSomething(b); }
};
这将进行深度优先遍历,直到它到达Bottom
个对象。
答案 1 :(得分:1)
您可以编写遍历一次并使用lambdas封装它。
void for_each_bottom( Top &top, const std::function<void(Bottom &)> &fn ) {
for (auto t = top.begin(); t != top.end(); ++t)
for (auto m = t->begin(); m != t->end(); ++m)
for (auto b = m->begin(); b != b->end(); ++b)
fn( *b );
}
void demo( Top &top ) {
for_each_bottom( top, []( Bottom &bottom ) {
ExecuteSomething( bottom );
} );
}
(如果您愿意,可以使用Jonathan Wakely的递归/模板方法进行遍历;这些嵌套循环很简单但不太通用。如果您愿意,也可以使用模板类型而不是std :: function&lt;&gt;。我通常除非需要,否则我们更愿意避开模板。)
答案 2 :(得分:0)
这里有一些递归函数的半伪代码应该可以解决这个问题:
void iterate(Container c)
{
for (Iterator iter = c.begin(); iter != c.end(); iter++)
{
if (*iter is a Container) // I forget how to do type-checking in C++
iterate(*iter);
else
ExecuteSomething(*iter);
}
}
编辑:
这样的东西可能更灵活(不记得C ++是否处理与C /不同的函数指针/有更好的方法来利用它们,但无论如何)
void recursiveIterateAndExecute(Container c, void func(Container))
{
for (Iterator iter = c.begin(); iter != c.end(); iter++)
{
if (*iter is a Container) // I forget how to do type-checking in C++
recursiveIterateAndExecute(*iter, func);
else
func(*iter);
}
}
有可能修改这些方法更符合STL算法,但由于我没有用C ++做很多工作,所以我无法对此做出真正的评论。