關於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 了\n\n";

                  else

                   std::cout << "沒有找到 10\n\n"; // 找一個不在數組中的元素

                  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 了\n\n";

                 else

                 std::cout << "沒有找到 50\n\n";

      只看標紅的這一句,這就是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表達式來寫。

  今天就分享到這里了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM