基于向量大小在for循环中擦除std :: vector的索引

塔尔博士

我创建了一个函数来过滤掉std :: vector中我不喜欢的元素,在本例中为opencv轮廓的向量。下面的代码看起来像是可以工作,但是不能,我怀疑是因为每当我删除索引时都会更改索引,但是我继续进行下一个i值迭代。

void FilterContours( std::vector<std::vector<cv::Point>> contours )
{
    for ( int i = 0; i < contours.size(); i++ ) {

        //Remove contours smaller than 5 from vector - example
        if ( contours[i].size() < 5 ) {
            contours.erase(contours.begin() + i);
            continue;
        }

        //Other filtering...
    }
    return;
}

因此,问题是,此功能是否可以按预期工作(我不认为可以),如果不能,则如何使它按预期工作?擦除后是否应该添加ai-= 1以保持正确的索引位置?

雷米·勒博

每次您erase()从容器中size()删除元素时,其元素的递减量以及其余元素的索引也会递减。但是您无条件地增加了循环计数器,因此,每次擦除一个元素时,都将跳过紧随其后的下一个元素!

此外,你是通过你vector的价值,所以你在工作拷贝vector,调用者不会看到在原来的任何变化vector

正确的方法是:

  1. 仅当不删除元素时,才在循环体内增加索引变量。当您确实要擦除元素时,请保持变量不变:

    void FilterContours( std::vector<std::vector<cv::Point>> &contours )
    {
        int i = 0;
        while ( i < contours.size() ) {
            if ( contours[i].size() < 5 ) {
                contours.erase(contours.begin() + i);
                continue;
            }
    
            //Other filtering...
    
            ++i;
        }
    }
    
  2. 使用迭代器代替索引:

    void FilterContours( std::vector<std::vector<cv::Point>> &contours )
    {
        auto it = contours.begin();
        while ( it != contours.end() ) {
            if ( it->size() < 5 ) {
                it = contours.erase(it);
                continue;
            }
    
            //Other filtering...
    
            ++it;
        }
    }
    
  3. 使用删除删除习惯用法:

    void FilterContours( std::vector<std::vector<cv::Point>> &contours )
    {
        contours.erase(
            std:::remove_if(
                contours.begin(),
                contours.end(),
                [](const std::vector<cv::Point> &v)
                {
                    if (v.size() < 5) return true; 
                    //Other filtering...
                    return false;
                }
            ),
            contours.end()
        );
    }
    

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何通过索引从std :: vector <>擦除元素?

在 std::vector 中索引名称

向量大小在for循环中创建问题

从std :: vector中的特定索引中删除

如何使用擦除功能通过索引从std :: vector <>擦除多个元素?

C ++ std :: vector :: data为什么返回的指针索引和向量索引不匹配?

向量大小在for循环中填充后返回0

根据索引删除循环中向量的元素

如何从基于范围的循环中的向量中擦除?

基于索引实例化for循环中的对象

将std :: string索引转换为std :: vector中的整数

如何在std :: vector <bool>中建立索引?

删除std :: set <vector <string >> :: iterator的索引处的值

在基于范围的for循环中从std :: vector <Object>获取指向Object的指针

在基于范围的for循环中使用shared_ptr到std :: vector

基于循环中的当前索引读取不同的索引

在Matlab中使用动态向量作为for循环中的索引值

访问“ for”循环中的索引?

嵌套循环中的索引

在 for 循环中索引

在 for 循环中增加索引

在 for 循环中重置索引

如何从对其中一项的引用中获取 std::vector 元素的索引?

如何从boost :: container :: vector <std :: string> :: iterator访问索引和对象?

在std :: vector上进行迭代:无符号vs有符号索引变量

使用std :: vector时如何将索引信息传递给元素构造函数?

获取std :: vector的迭代器索引的最有效方法是什么?

同时写入std :: vector到不同索引会导致崩溃吗?

查找像`std :: vector`这样的索引数据结构(不是数组)