关于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表达式来写。

  今天就分享到这里了

原文地址:https://www.cnblogs.com/songyuchen/p/13940171.html