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

本文介绍了如何使用STL的find和find_if函数对数组、STL容器进行查找,包括基本类型和自定义类型的查找方法。针对自定义类型,文章详细解释了如何通过重载运算符或自定义谓词函数实现特定条件的查找。

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

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

文章来源:http://www.codelast.com/

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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类定义如下:

1
2
3
4
5
6
7
class CPerson
{
public:
CPerson(void); ~CPerson(void);
public:
int age; // 年龄
};
那么如何用find()函数进行查找呢?这时,我们需要提供一个判断两个CPerson对象“相等”的定义,find()函数才能从一个list中找到与指定的CPerson“相等”的元素。
文章来源:http://www.codelast.com/
这个“相等”的定义,是通过重载“==”操作符实现的,我们在CPerson类中添加一个方法,定义为:
1
bool operator==(const CPerson &rhs) const;
实现为:
1
2
3
4
bool CPerson::operator==(const CPerson &rhs) const
{
return (id == rhs.age);
}
 
然后我们就可以这样查找(假设list中已经有了若干CPerson对象)了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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的元素,找到的话就得到对象的指针。
文章来源:http://www.codelast.com/
这时候,你不再能像上面的例子那样做,我们需要用到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类外部定义这样一个结构体:
1
2
3
4
5
6
7
8
9
10
11
12
typedef struct finder_t
{
finder_t(int n)
: age(n)
{
}
bool operator()(CPerson *p)
{
return (age == p->age);
}
int age;
}finder_t;
然后就可以利用find_if函数来查找了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
}
if (it != lst.end()) // 找到了
{
// do something
}
else // 没找到
{
// do something
}
 
return 0;
 
}
### 使用 `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]。然而一旦引入额外约束条件之后,就不得不退回到通用序列处理模式下了,这时候整体效率可能会有所下降取决于输入规模大小等因素影响。 因此建议开发者权衡好需求优先级后再做决定:如果是简单属性过滤的话继续沿用原生接口会更加高效简洁明了些;反之遇到较为特殊的情况再考虑混合编程风格也不迟。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值