C++ vector的 *** 作

C++ vector的 *** 作,第1张

C++ vector的 *** 作

flyfish

文章目录
  • C++ vector的 *** 作
    • 删除符合条件的元素
    • remove_if与erase结合删除 方式1
    • remove_if与erase结合删除 方式2
    • remove_if与erase结合删除 方式3 类对象方式
    • remove_if与erase结合删除 方式4
    • 为什么删除元素需要remove_if和erase配合呢
    • 移动元素
    • 删除重复的元素
    • 一个vector里的值赋值给另一个vector
    • 一个vector的元素写入另一个vector的末尾
    • 两个vector拷贝到另一个vector中
    • 复制符合条件的元素

版本C++11

删除符合条件的元素

常见但不推荐的方法

#include 
#include 
#include 
int main ()
{
    std::vector<int> vec;
    for(int i=0;i<10;i++)
    {
        vec.push_back(i);
    }

    std::vector<int>::iterator iter = vec.begin();
    while (iter != vec.end())
    {
        if ((*iter)%2==1)
        {

            iter = vec.erase(iter); //删除元素之后,iter指向已删除元素的下一个位置
        }
        else
            ++iter; //指向下一个元素位置
    }

    //输出结果 方式1 //0 2 4 6 8
    std::for_each(vec.begin(), vec.end(), [](int i){ std::cout << i << ' '; });

    //输出结果 方式2 //0 2 4 6 8
    for (auto &i : vec)
    {
        std::cout << i << ' ';
    }

}
remove_if与erase结合删除 方式1
#include 
#include 
#include 

bool IsOdd (int i) { return ((i%2)==1); }
int main ()
{
    std::vector<int> vec;
    for(int i=0;i<10;i++)
    {
        vec.push_back(i);
    }

    vec.erase(std::remove_if(vec.begin(), vec.end(), IsOdd), vec.end());

    //输出结果 //0 2 4 6 8
    std::for_each(vec.begin(), vec.end(), [](int i){ std::cout << i << ' '; });

}
remove_if与erase结合删除 方式2
#include 
#include 
#include 

int main ()
{
    std::vector<int> vec;
    for(int i=0;i<10;i++)
    {
        vec.push_back(i);
    }
    
    vec.erase(std::remove_if(vec.begin(), vec.end(), [](int i ){ return ((i%2)==1); }), vec.end());
    //输出结果 //0 2 4 6 8
    std::for_each(vec.begin(), vec.end(), [](int i){ std::cout << i << ' '; });
    
}
remove_if与erase结合删除 方式3 类对象方式
#include 
#include 
#include 

class C
{ public:
    int m1;
    int m2;
};


int main ()
{
    std::vector<C> vec;
    for(int i=0;i<10;i++)
    {
        C t;
        t.m1=i;
        t.m2=i*2;
        vec.push_back(t);
    }


    vec.erase(std::remove_if(vec.begin(), vec.end(), [](C t ){ return ((t.m1%2)==1); }), vec.end());
    //输出结果 //0 2 4 6 8
    std::for_each(vec.begin(), vec.end(), [](C& t){ std::cout << t.m1 << ' '; });

}
remove_if与erase结合删除 方式4
#include 
#include 
#include 

int main ()
{

    std::vector<int> vec;
    for(int i=0;i<10;i++)
    {
        vec.push_back(i);
    }


    auto IsOdd = [](int i) -> bool
    {
        { return ((i%2)==1); }
    };

    vec.erase(std::remove_if(vec.begin(), vec.end(), IsOdd), vec.end());
    //输出结果 //0 2 4 6 8
    std::for_each(vec.begin(), vec.end(), [](int i){ std::cout << i << ' '; });

}
为什么删除元素需要remove_if和erase配合呢

通过一个例子来说明

#include 
#include 
#include 
int main ()
{
std::vector<int> vec{ 1,1,2,3,4,5,6 };
auto removeNumbers = [&](int number) -> bool
{
    return number < 3;
};
auto iterator = std::remove_if(vec.begin(), vec.end(), removeNumbers);
vec.erase(iterator, vec.end());
std::for_each(vec.begin(), vec.end(), [](int i){ std::cout << i << ' '; });
}



分析

#include 
#include 
#include 

//remove_if_custom等同于remove_if
template 
  ForwardIterator remove_if_custom (ForwardIterator begin, ForwardIterator end,
                             UnaryPredicate pred)
{
  ForwardIterator result = begin;
  while (begin!=end) {
    if (!pred(*begin)) {
      if (result!=begin)
        *result = std::move(*begin);
         std ::cout <<(*result)< vec{ 1,1,2,3,4,5,6 };
auto removeNumbers = [&](int number) -> bool
{
    return number < 3;
};
auto iterator = remove_if_custom(vec.begin(), vec.end(), removeNumbers);
std::for_each(vec.begin(), vec.end(), [](int i){ std::cout << i << ' '; });
std ::cout <

将范围[begin,end]转换为 删除了pred返回TRUE的所有元素的范围[iterator,end],并将迭代器返回到该范围的新末尾。



因为remove_if移动了想要保留的元素,erase才是真正的删除。


把[iterator,end]元素删除,剩下得就是想要的

该函数不能更改容器的大小,删除是通过将pred返回TRUE的元素替换为下一个不返回TRUE的元素来完成的,
例如vector{ 1,1,2,3,4,5,6 },第一个1 用 3 替换,第二个1用4替换,2用5替换,依此类推

未移除的元素的相对顺序被保留,而返回的迭代器和最后一个元素之间的元素保持有效但未指定的状态。



例如经过remove_if输出3 4 5 6 4 5 6 ,未移除的元素是最后的4 5 6相对顺序被保留

移动元素
#include 
#include 
#include 

int main ()
{



    std ::vector<int> vec{10, 20, 30, 10, 20, 30};
    //移动之前 10 20 30 10 20 30
    std::for_each(vec.begin(), vec.end(), [](int i){ std::cout << i << ' '; });
    std ::cout <<std::endl;


    std ::vector<int>::iterator  pend = std ::remove(vec.begin(), vec.end(), 20);
    //移动之后,结尾选择新的迭代器 10 30 10 30
    std::for_each(vec.begin(), pend, [](int i){ std::cout << i << ' '; });
    std ::cout <<std::endl;


}
删除重复的元素
#include 
#include 
#include 

int main()
{
    std::vector v = { 1,1,3,3,2,2 };
    
    std::sort(v.begin(), v.end());
    
    std::vector::iterator pos=std::unique(v.begin(), v.end());
    
    v.erase(pos, v.end());
    
    std::for_each(v.begin(), v.end(), [](int i){ std::cout << i << ' '; });
    
    //1 2 3
    return 0;
}
一个vector里的值赋值给另一个vector
#include 
#include 
#include 
int main ()
{

    std ::vector<int> vec{10, 20, 30, 10, 20, 30};
    std ::vector<int> new_vec{1,2,3};

    new_vec.assign (vec.begin(),vec.end());
    std::for_each(new_vec.begin(), new_vec.end(), [](int i){ std::cout << i << ' '; });
    //10 20 30 10 20 30
    return 0;
}

new_vec的值被新的值覆盖

一个vector的元素写入另一个vector的末尾
#include 
#include 
#include 
int main ()
{

    std ::vector<int> vec{10, 20, 30, 10, 20, 30};
    std ::vector<int> new_vec{1,2,3};

    new_vec.insert(new_vec.end(), vec.begin(), vec.end());
    std::for_each(new_vec.begin(), new_vec.end(), [](int i){ std::cout << i << ' '; });
    //1 2 3 10 20 30 10 20 30

    return 0;
}
两个vector拷贝到另一个vector中
#include 
#include 
#include 
int main ()
{

    std ::vector<int> vec1{10, 20, 30, 10, 20, 30};
    std ::vector<int> vec2{1,2,3};
    std ::vector<int> new_vec;

    std::copy(vec1.begin(), vec1.end(), std::back_inserter(new_vec));
    std::copy(vec2.begin(), vec2.end(), std::back_inserter(new_vec));

    std::for_each(new_vec.begin(), new_vec.end(), [](int i){ std::cout << i << ' '; });
    //10 20 30 10 20 30 1 2 3

    return 0;
}
复制符合条件的元素
#include 
#include 
#include 
#include 
#include 

int main()
{
    std::vector<int> from_vector(10);
    std::iota(from_vector.begin(), from_vector.end(), 0);
    //=  std ::vector vec{1,2,3,4,5,6,7,8,9};
    std::for_each(from_vector.begin(), from_vector.end(), [](int i){ std::cout << i << ' '; });
    std ::cout <<std::endl;


    std::vector<int> to_vector;
    to_vector.clear();
    std::copy_if(from_vector.begin(), from_vector.end(),
                 std::back_inserter(to_vector),
                 [](int x) { return x % 2 == 0; });

    std::for_each(to_vector.begin(), to_vector.end(), [](int i){ std::cout << i << ' '; });
    //0 2 4 6 8
    std ::cout <<std::endl;


}

参考
https://en.cppreference.com/w/cpp/algorithm
https://www.cplusplus.com/reference/algorithm/remove_if/
https://studiofreya.com/cpp/std-remove_if-with-lambda/

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/607863.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-14
下一篇 2022-04-14

发表评论

登录后才能评论

评论列表(0条)