2

我有一个包含 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());

哪一个可以在一行中工作?像这样的东西?谢谢!

4

3 回答 3

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对象。

于 2012-06-06T17:18:09.310 回答
1

您可以编写一次遍历并使用 lambda 封装它。

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<>。我通常更喜欢避免使用模板除非需要。)

于 2012-06-06T17:20:13.603 回答
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++ 做太多工作,所以我无法对此发表评论。

于 2012-06-06T16:21:31.633 回答