• 关于STL容器中std::find,std::find_if以及Lambda表达式的用法说明


    最近因为一直在面试,所以一直在准备,现在工作总算是有点着落了,所以就继续开始我的学习之旅。今天我们来总结STL容器中的std::find,std::find_if以及LAMABDA表达式的用法。为什么会突然写这个呢?这是因为最近笔者最近碰到一个技术问题,就是我有一些长的字符串(20位以上)(存放到list中的元素类中的某个成员变量中),然后呢,因为某些原因,底层上报上来的字符串有重复,那么我们现在需要把它过滤掉,有什么好办法呢?首先用memcmp这种方法是不可能的,算法效率太低了。能想到的有这几种。

      一、可以采用set容器把这些东西全部导入进去,然后在把它导出来就好了。但是这样做有个缺点,就是因为我后面都用这个list读取数据,如果都改会比较麻烦,所以我果断放弃了。

      二、可以采用hash校验的方法,这个方法需要添加算法不说,最终要的是我这边生成的hash校验和字符串校验差不多长度,压根也没这必要。

      三、采用STL容器中的find和find_if的用法来进行处理,我果断选择了第三种。

      好,接下来我们开始研究一下这些内容。

      一、STL容器中find的用法

      二、STL容器中find_if的用法

      三、LAMBDA表达式到底是个啥?

      四、为什么要用LABMBDA表达式

      一、STL容器中find的用法

        首先说一下,STL容器中有很多find,比如说set,map。他们内部都有内置的find函数,一般情况下,如果我们用到这些容器,那么我们直接用它的内置find就可以了。(这是因为map和set中内置的find函数比std::find时间复杂度要低,速度更快)。但是像list,vector这些容器是没有find函数的,所以我们只能用默认的std::find来进行查找。首先说一下find函数的原型

              template<class InputIterator, class T>  

             InputIterator find ( InputIterator first, InputIterator last, const T& value )   

             {  

            for ( ;first!=last; first++) 

      if ( *first==value ) break;  

            return first;  

             }  

      我们从find的定义中可以看到,find内部一共包含三个参数,第一个参数和第二个参数指的是迭代器的头部和尾端,而第三个参数表示的是要比较的值。(不过这里要注意这个值必须是const类型的,所以我们在后面的赋值过程中也要赋值成const类型)。

      废话不说,看一个最简单的例子。

                 std::vector<int> score{ 10, 20, 30, 40 };    // 待查找

                       key int find_key_10 = 10; // 找一个存在于数组中的元素

                      auto ret_val_1 = std::find(score.begin(), score.end(), find_key_10);

                      if (score.end() != ret_val_1)

                      std::cout << "找到了 10 了 ";

                      else

                       std::cout << "没有找到 10 "; // 找一个不在数组中的元素

                      int find_key_50 = 50;

                      auto ret_val_2 = std::find(score.begin(), score.end(), find_key_50);

                     if (score.end() != ret_val_2)

                     std::cout << "找到了 50 了 ";

                     else

                     std::cout << "没有找到 50 ";

          只看标红的这一句,这就是find的一个最简单的用法,第一个参数和第二个参数分别传递STL容器的头端和尾端,而第三个参数我们直接传入一个常量,然后直接进行判断,如果说没有找到,那么它返回的值一定是到尾端,反之返回的就是中间的迭代器。

        但是这里有个问题,那就是如果说我们传入的vector或者list容器不是一个基本类型呢?比如说这样:  

    class CPerson
    {
    public:
        CPerson(void); 
        ~CPerson(void);

      int getage(){return age;

      }

    private:
        int age; // 年龄
    };

    我们这里要比较其中的age是否相等,那么我们仿照上面的例子应该怎么书写呢

      std::vector<Cperson> score;

      // 插入数据

      CPerson c;

      c.age = 20;

      auto ret_val_2 = std::find(score.begin(), score.end(), c);

      // 比较

      好的,那么我们根据find的定义来分析一下这个find语句,根据find定义,我们执行过程会是这样

      for ( ;first!=last; first++) 

      if ( *first==c ) break;  

            return first;  

      这样就变成了类进行比较,不用说,编译肯定是报错的。而且也没有按照我们的age来解决。

      那么我们该怎么解决这个问题呢?其实问题的关键就在于first==c这句话上,所以我们最容易的解决方案就是重载==运算符。我们可以在类中添加这样的话。

      

    class CPerson
    {
    public:
        CPerson(void); 
        ~CPerson(void);

      int getage(){return age;

      }

      bool CPerson::operator==(const CPerson &rhs) const
        {
            return (age == rhs.age);
        }

    private:
        int age; // 年龄
    };

    这样问题就解决了。

    但是这样设置的条件有点窄,比如说我如果要求找到的这个值自动在类中加30怎么办呢?这就需要find_if函数了。

      我们首先来看一下find_if的用法

          template<class InputIterator, class Predicate>
          InputIterator find_if(InputIterator _First, InputIterator _Last, Predicate _Pred);

      我们从find_if定义上可知,find_if上也有三个参数,其中前两个参数是和find代表是相同的,但是第三个参数是我们自定义的函数。

      直接上例子:

      

    class CPerson
    {
    public:
        CPerson(void); 
        ~CPerson(void);

      int getage(){return age;

      }

      bool CPerson::operator() (const CPerson &rhs) const
        {
            if (age == rhs.age) {

        rhs.age +=30;

        return true;

      }
        }

    private:
        int age; // 年龄
    };

     std::vector<Cperson> score;

      // 插入数据

      CPerson c;

      c.age = 20;

      auto ret_val_2 = std::find_if(score.begin(), score.end(), c);

      这里的区别在于之前是重载了==,现在是重载了(),换句话说,这里的空间要大一些。

      三、LAMBMA表达式

        当然,作为一个懒人其实还有一种方法,那就是把LAMBDA表达式融入到其中,我们可以这样写:

        int age = 30;

        auto ret_val_2 = std::find_if(score.begin(), score.end(), [age](const  Cperson  &rhs))-> bool {

          return age == rhs.getage();

        } 

        这里要说的一点就是getage返回必须是个常量,因为find_if就是这么定义的。

      四、说一下为什么要用LAMBMA表达式

        使用LAMBDA表达式有两个原因,第一个原因在于LAMBDA表达式时在函数中间定义,这样比较好查找。

        第二个原因在于LAMBDA表达式使用起来比较方便,可以直接操纵动态参数,如果不然我们还得重新写一个构造函数,把参数传进去进行比较,多有不便,综上所述,所以一般我都用LAMBDA表达式来写。

      今天就分享到这里了

  • 相关阅读:
    和程序员有关的对联
    《kali linux 渗透测试初级教程》免费下载
    PPT嵌入字体的方法
    修改nw.js的exe文件使其请求管理员权限
    nw.js FrameLess Window下的窗口拖拽与窗口大小控制
    nw.js如何处理拖放操作
    nw.js 软件推荐:AxeSlide斧子演示:PPT的另一种可能(转)
    c#使用word、excel、pdf ——转
    ASP.NET MVC
    http 报文
  • 原文地址:https://www.cnblogs.com/songyuchen/p/13940171.html
Copyright © 2020-2023  润新知