std::find,std::find_if对类进行查找

STL的find,find_if函数提供了一种对数组、STL容器进行查找的方法。使用该函数,需 #include <algorithm>

我们查找一个list中的数据,通常用find(),例如:

 

using namespace std;

 

int main()

{

list<int> lst;

lst.push_back(10);

lst.push_back(20);

lst.push_back(30);

 

list<int>::iterator it = find(lst.begin(), lst.end(), 10); // 查找list中是否有元素“10”

if (it != lst.end()) // 找到了

{

// do something 

}

else // 没找到

{

// do something

}

 

return 0;

}

 

那么,如果容器里的元素是一个类呢?例如,有list<CPerson> ,其中CPerson类定义如下:

 

class CPerson

{

public:

CPerson(void); ~CPerson(void);

 

public:

int age; // 年龄

};

 

那么如何用find()函数进行查找呢?这时,我们需要提供一个判断两个CPerson对象“相等”的定义,find()函数才能从一个list中找到与指定的CPerson“相等”的元素。

这个“相等”的定义,是通过重载“==”操作符实现的,我们在CPerson类中添加一个方法,定义为:

 

bool operator==(const CPerson &rhs) const;

 

实现为:

 

 

bool CPerson::operator==(const CPerson &rhs) const

{

return (id == rhs.age);

}

然后我们就可以这样查找(假设list中已经有了若干CPerson对象)了:
list<CPerson> lst;
//
// 向lst中添加元素,此处省略
//
CPerson cp_to_find; // 要查找的对象
cp_to_find.age = 50;
list<CPerson>::iterator it = find(list.begin(), list.end(), cp_to_find); // 查找

if (it != lst.end()) // 找到了

{

// do something 

}

else // 没找到

{

// do something

}

 

 

 

这样就实现了需求。

 

 

有人说,如果我有自己定义的“相等”呢?例如,有一个list<CPerson*>,这个list中的每一个元素都是一个对象的指针,我们要在这个list中查找具有指定age的元素,找到的话就得到对象的指针。

这时候,你不再能像上面的例子那样做,我们需要用到find_if函数,并自己指定predicate function(即find_if函数的第三个参数,请查阅STL手册)。先看看find_if函数的定义:

 

 

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

An input iterator addressing the position of the first element in the range to be searched.

_Last

An input iterator addressing the position one past the final element in the range to be searched.

_Pred

User-defined predicate function object that defines the condition to be satisfied by the element being searched for. A predicate takes single argument and returns true or false.

我们在CPerson类外部定义这样一个结构体:
typedef struct finder_t
{
finder_t(int n ) : age (n ) { } bool operator()(CPerson *p) { return (age == p->age ); } int age ;
}finder_t;
然后就可以利用find_if函数来查找了:
list<CPerson*> lst;
//
// 向lst中添加元素,此处省略
//
list<CPerson*>::iterator it = find_if(lst.begin(), lst.end(), finder_t(50)); // 查找年龄为50的人

if (it != lst.end()) // 找到了

{

cout << "Found person with age : " << (*it)->age;

}

else // 没找到

{

// do something

}

 

### 使用 `std::find_if` 和 `std::map` 在 C++ 中,`std::map` 是一种关联容器,它存储键值对并按键自动排序。虽然可以直接通过 `operator[]` 或者 `.at()` 方法访问特定的键值对,但在某些场景下可能需要更复杂的条件来查找某个元素。此时可以借助标准库中的算法函数 `std::find_if` 来完成。 #### 实现方式 尽管 `std::map` 提供了自己的查找方法(如 `.find`, `.count`, `.lower_bound` 等),但这些方法通常只支持基于键的精确匹配。如果希望执行自定义逻辑的查找,则可以结合 `std::find_if` 函数实现这一目标。以下是具体用法: 1. **迭代器范围** 需要提供一个有效的迭代器范围给 `std::find_if`,对于 `std::map` 可以使用其成员函数 `.begin()` 和 `.end()` 获取整个映射的范围。 2. **谓词函数** 定义一个返回布尔型的函数或者 lambda 表达式作为谓词参数传入 `std::find_if`,该谓词用于判断当前遍历到的元素是否满足指定条件。 3. **调用形式** 将上述两个部分组合起来即可形成完整的调用语句。 下面是具体的代码示例[^1]: ```cpp #include <iostream> #include <map> int main() { std::map<int, std::string> myMap = {{1, "one"}, {2, "two"}, {3, "three"}}; // 查找 value 值长度大于 3 的第一个元素 auto result = std::find_if(myMap.begin(), myMap.end(), [](const std::pair<const int, std::string>& elem) -> bool { return elem.second.length() > 3; }); if (result != myMap.end()) { std::cout << "Found element with key=" << result->first << ", value='" << result->second << "'\n"; } else { std::cout << "No matching element found.\n"; } return 0; } ``` 在这个例子中,我们创建了一个简单的整数到字符串的映射表,并尝试找到其中具有较长字符串值的第一个条目。注意这里使用的 Lambda 表达式的捕获列表为空(`[]`)表示不捕捉外部变量;而形参型则显式声明为 const 引用以便提高性能同时避免不必要的拷贝操作。 另外需要注意的是,在实际应用过程中应当始终验证由 `std::find_if` 返回的结果指针是否等于结束标记(end iterator),以此确认是否存在符合条件的目标对象。 --- ### 性能考量 当涉及到频繁查询时,应该考虑到不同数据结构之间的差异以及它们各自适用的最佳实践。例如,相比于单纯依靠线性扫描的方式来说,利用内置二分搜索机制的标准 STL 关联型容器往往能够带来更好的时间复杂度表现——即 O(log n)[^4]。然而一旦引入额外约束条件之后,就不得不退回到通用序列处理模式下了,这时候整体效率可能会有所下降取决于输入规模大小等因素影响。 因此建议开发者权衡好需求优先级后再做决定:如果是简单属性过滤的话继续沿用原生接口会更加高效简洁明了些;反之遇到较为特殊的情况再考虑混合编程风格也不迟。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值