工作中经常遇见的一个场景:判断某个元素是否在vector容器中。
当然,会有很多种方法,由内置数据类型到自定义数据类型,下面简单总结一下。
【1】内置数据类型
代码胜过一切文档。如下示例代码:
#include <iostream>
#include <vector>
#include <string>
// 为了便于示例,声明全局容器
std::vector<std::string> strVec;
void methods(const std::string& target)
{
// 方法一:遍历容器,查找相等元素判断是否存在
{
for (const auto& item : strVec)
{
if (item == target)
{
std::cout << "method1: find " << target << " exists." << std::endl;
break;
}
}
}
// 方法二:获取元素个数,通过个数判断是否存在
{
int nCount = std::count(strVec.begin(), strVec.end(), target);
if (nCount > 0)
{
std::cout << "method2: find " << target << " exists." << std::endl;
}
}
// 方法三:查询元素迭代器,通过迭代器有效性判断是否存在
{
auto iter = std::find(strVec.begin(), strVec.end(), target);
if (iter != strVec.end())
{
std::cout << "method3: find " << target << " exists." << std::endl;
}
}
// 方法四:查询相等元素的迭代器,通过迭代器有效性判断是否存在
{
auto iter = std::find_if(strVec.begin(), strVec.end(), [&](const std::string& item)->bool
{ return (item == target); });
if (iter != strVec.end())
{
std::cout << "method4: find " << target << " exists." << std::endl;
}
}
}
int main()
{
strVec = { "C", "C++", "Java", "Python", "Lua", "Sql" };
// 场景1:查找Ruby
std::cout << "Find Ruby" << std::endl;
methods("Ruby");
// 场景2:查找C++
std::cout << "Find C++" << std::endl;
methods("C++");
system("pause");
return 0;
}
// result
/*
Find Ruby
Find C++
method1: find C++ exists.
method2: find C++ exists.
method3: find C++ exists.
method4: find C++ exists.
*/
【2】自定义数据类型
代码胜过一切文档。如下示例代码:
#include <iostream>
#include <map>
#include <string>
#include <vector>
struct Student
{
std::string code; // 学号(唯一性标识)
int grade; // 年级
std::map<std::string, double> scores; // <科目,成绩>
bool operator==(const Student& obj) const
{
return obj.code == code; // 只要学号相同即可
}
};
// 为了便于示例,声明全局容器
std::vector<Student> vecStu;
void methods(const Student& target)
{
// 方法一:遍历容器,查找相等元素判断是否存在
{
for (const auto& item : vecStu)
{
if (item == target)
{
std::cout << "method1: find exists." << std::endl;
break;
}
}
}
// 方法二:获取元素个数,通过个数判断是否存在
{
int nCount = std::count(vecStu.begin(), vecStu.end(), target);
if (nCount > 0)
{
std::cout << "method2: find exists." << std::endl;
}
}
// 方法三:查询元素迭代器,通过迭代器有效性判断是否存在
{
auto iter = std::find(vecStu.begin(), vecStu.end(), target);
if (iter != vecStu.end())
{
std::cout << "method3: find exists." << std::endl;
}
}
// 方法四:查询相等元素的迭代器,通过迭代器有效性判断是否存在
{
if (std::find_if(vecStu.begin(), vecStu.end(), [&](const Student& obj)->bool
{ return (obj == target); }) != vecStu.end())
{
std::cout << "method4: find exists." << std::endl;
}
}
}
int main()
{
vecStu.push_back({ "080605109", 6, { {"English", 100}, {"China", 100} } });
vecStu.push_back({ "080605110", 7, { {"English", 99}, {"China", 70} } });
vecStu.push_back({ "080605111", 8, { {"English", 98}, {"China", 69} } });
vecStu.push_back({ "080605112", 6, { {"English", 97}, {"China", 68} } });
vecStu.push_back({ "080605113", 7, { {"English", 96}, {"China", 67} } });
Student obj = { "080605114", 8, { {"English", 95}, {"China", 66} } };
vecStu.push_back(obj);
// 场景1:查找学号为[0806005109]的学生,我们暂不关注成绩
std::cout << "Find code: 0806005108" << std::endl;
methods(Student{ "0806005108", {} });
// 场景2:查找学号为[0806005114]的学生,我们暂不关注成绩
std::cout << "Find code: 0806005114" << std::endl;
methods(obj);
// 场景3:不想通过学号,只想查找六年级,是否存在英语和语文全为满分的学生
auto iter = std::find_if(vecStu.begin(), vecStu.end(), [&](const Student& obj)->bool
{ return (obj.grade == 6 &&
obj.scores.find("English")->second == 100 &&
obj.scores.find("China")->second == 100); });
if (iter != vecStu.end())
{
std::cout << "method: find 100 exists." << std::endl;
}
return 0;
}
// result
/*
Find code: 0806005108
Find code: 0806005114
method1: find exists.
method2: find exists.
method3: find exists.
method4: find exists.
method: find 100 exists.
*/
注意:自定义数据类型,必须重载==符号。
原因很简单:遇见这种场景,计算机弄不明白你想让它以什么标准来判断两个对象相等,所以你得给它确定了相等的标准或准则。
综上所述,再强调一点:针对自定义数据类型,使用std::find_if方法,显而易见,自由度很大。