将矢量中的每个项目与其他项目进行比较,同时删除一些元素?

时间:2017-12-07 18:12:43

标签: c++ loops vector polymorphism shared-ptr

我需要编写一个函数,将std::vector<std::shared_ptr<Shape >> shapes_的每个元素与每个其他元素进行比较,确定形状是否重叠,然后删除其中一个重叠形状(如果是这样)。这是我目前所拥有的:

class Shape {
    public:
    ...
        virtual bool overlaps(const std::shared_ptr<Shape>&) const = 0;
    ...
};

class Square : public Shape { ... } ;
class Circle : public Shape { ... } ;

利用这些课程:

std::vector<shared_ptr<Shape>> shapes_; 

// ... some code populates the array

for (auto& shape : shapes_) {
    // Compare to every other shape
    for (unsigned long j = 0; j < shapes_.size(); j++) {
        // If they overlap and they aren't the same shape
        if (shape->overlaps(shapes_.at(j)) && shape!=shapes_.at(j)) {
            shapes_.erase(shapes_.begin() + j);
        }
    }
}

然而,我一直在遇到问题,我在迭代一个null(已移除)元素,或超出数组的末尾或其他东西。我一直在以这种方式重新配置它,但是其中一个问题不断出现。

在将一个向量的每个元素与其他元素进行比较时,处理问题的最明智,最干净的方法是什么,并且在此过程中有时会删除一些元素?

此外,如果我想打印一些有关找到的重叠信息以及删除的形状,该怎么办?

1 个答案:

答案 0 :(得分:2)

您可以使用erase-remove惯用语:

auto it = vec.begin();
auto end = vec.end();
while( std::distance( it, end ) > 1 ) {
     auto condition = [shape=*it]( const auto &other ) { return shape->overlaps( other ); };
     end = std::remove_if( ++it, end, condition );
}
vec.erase( end, vec.end() );

这个lambda语法需要C ++ 14,但如果需要,可以很容易地修改它以使用C ++ 11(例如,在lambda之前引入临时变量shape,或者通过以下方式捕获it不参考)。