首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++ std::向量搜索值

c++ std::向量搜索值
EN

Stack Overflow用户
提问于 2013-01-02 23:15:57
回答 4查看 37.3K关注 0票数 11

我正在尝试优化一个基于索引的std::vector“搜索”,遍历一个向量并返回匹配“搜索”条件的和元素。

代码语言:javascript
复制
struct myObj {
   int id;
   char* value;
};

std::vector<myObj> myObjList;

创建几千个具有唯一id和值的条目,并将它们推送到向量myObjList

检索与id匹配的myObj的最有效方法是什么。目前,我正在进行如下索引迭代:

代码语言:javascript
复制
for(int i = 0; i < myObjList.size(); i++){
   if(myObjList.at(i).id == searchCriteria){
    return myObjList.at(i);
   }
}

注:searchCriteria = int。所有的元素都有唯一的id,上面的方法可以完成任务,但可能不是最有效的方法。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-01-02 23:20:55

C++标准库有一些抽象的算法,这给了C++一种函数式的味道,我称之为函数式,它让您更专注于搜索的标准,而不是如何实现搜索本身。这适用于许多其他算法。

您正在寻找的算法是std::find_if,这是一个遍历迭代器范围的简单线性搜索。

在C++11中,您可以使用lambda来表达您的标准:

代码语言:javascript
复制
std::find_if(myObjList.begin(), myObjList.end(), [&](const myObj & o) {
    return o.id == searchCriteria;
});

当C++11不可用时,您必须提供一个谓词(function object (=functor)或function pointer),如果提供的实例是您要查找的实例,则该谓词返回true。函数器的优点是它们可以被参数化,在你的例子中,你想用你正在寻找的ID来参数化函数器。

代码语言:javascript
复制
template<class TargetClass>
class HasId {
    int _id;
public:
    HasId(int id) : _id(id) {}
    bool operator()(const TargetClass & o) const {
        return o.id == _id;
    }
}

std::find_if(myObjList.begin(), myObjList.end(), HasId<myObj>(searchCriteria));

此方法返回一个迭代器,指向找到的第一个符合条件的元素。如果没有这样的元素,则返回结束迭代器(它指向向量的末尾,而不是最后一个元素)。因此,您的函数可能如下所示:

代码语言:javascript
复制
vector<myObj>::iterator it = std::find_if(...);

if(it == myObjList.end())
    // handle error in any way
else
    return *it;
票数 19
EN

Stack Overflow用户

发布于 2013-01-02 23:17:04

使用std::find_if

参考页面上有一个示例。

下面是一个更符合您的问题的工作示例:

代码语言:javascript
复制
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

struct myObj
{
   int id;
   char* value;

   myObj(int id_) : id(id_), value(0) {}
};

struct obj_finder
{
    obj_finder(int key) : key_(key)
    {}

    bool operator()(const myObj& o) const
    {
        return key_ == o.id;
    }

    const int key_;
};

int main () {
  vector<myObj> myvector;
  vector<myObj>::iterator it;

  myvector.push_back(myObj(30));
  myvector.push_back(myObj(50));
  myvector.push_back(myObj(100));
  myvector.push_back(myObj(32));

  it = find_if (myvector.begin(), myvector.end(), obj_finder(100));
  cout << "I found " << it->id << endl;

  return 0;
}

而且,如果您有可用的C++11,您可以使用lambda使其更简洁:

代码语言:javascript
复制
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

struct myObj
{
   int id;
   char* value;

   myObj(int id_) : id(id_), value(0) {}
};

int main ()
{
  vector<myObj> myvector;
  vector<myObj>::iterator it;

  myvector.push_back(myObj(30));
  myvector.push_back(myObj(50));
  myvector.push_back(myObj(100));
  myvector.push_back(myObj(32));

  int key = 100;

  it = find_if (myvector.begin(), myvector.end(), [key] (const myObj& o) -> bool {return o.id == key;});
  cout << "I found " << it->id << endl;

  return 0;
}
票数 11
EN

Stack Overflow用户

发布于 2013-01-02 23:34:14

这并不是对你问题的真正回答。其他回答的人给出了非常好的答案,所以我没有什么要补充的。

但我想说的是,您的代码并不是非常地道的C++。当然,真正惯用的C++会使用::std::find_if。但是,即使您没有::std::find_if,您的代码仍然不是惯用的。我将提供两次重写。一次是C++11重写,第二次是C++03重写。

首先,C++11:

代码语言:javascript
复制
for (auto &i: myObjList){
   if(i.id == searchCriteria){
      return i;
   }
}

第二,C++03:

代码语言:javascript
复制
for (::std::vector<myObj>::iterator i = myObjList.begin(); i != myObjList.end(); ++i){
   if(i->id == searchCriteria){
      return *i;
   }
}

遍历任何类型的C++容器的标准方法是使用迭代器。向量可以用整数来索引,这是很好的。但是,如果您不必要地依赖于该行为,那么如果您以后应该更改数据结构,则会使自己变得更加困难。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14124395

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档