【问题标题】:find in std::vector<std::pair>在 std::vector<std::pair> 中查找
【发布时间】:2013-03-08 03:11:57
【问题描述】:

我有一个成对的向量。对中的第一个是 std::string 类型,第二个是 Container 类型。

std 或 boost 中存在哪些方便的功能,以便我可以在给定字符串值作为键的情况下返回一个 Container?

更新

有人评论说我可以使用 std::map 代替,但我实际上需要保留我的项目的顺序,按照我将它们推送到向量的顺序。

【问题讨论】:

  • 在这种情况下,为什么是std::vector 而不是std::map
  • std::find_if 和自定义谓词(C++11 中的 lambda)
  • @Andy Prowl 我已将我的问题标记为 c++98
  • @meh 我需要保留向量中项目的顺序
  • @Baz:对不起,我错过了标签。嗯,答案是一样的,除了括号内的部分

标签: c++ boost std c++98


【解决方案1】:

一个可能的解决方案:

struct comp
{
    comp(std::string const& s) : _s(s) { }

    bool operator () (std::pair<std::string, Container> const& p)
    {
        return (p.first == _s);
    }

    std::string _s;
};

// ...

typedef std::vector<std::pair<std::string, Container> > my_vector;
my_vector v;

// ...

my_vector::iterator i = std::find_if(v.begin(), v.end(), comp("World"));
if (i != v.end())
{
    Container& c = i->second;
}

// ...

这是一个完整的例子:

#include <vector>
#include <utility>
#include <string>
#include <algorithm>

struct Container
{
    Container(int c) : _c(c) { }
    int _c;
};

struct comp
{
    comp(std::string const& s) : _s(s) { }

    bool operator () (std::pair<std::string, Container> const& p)
    {
        return (p.first == _s);
    }

    std::string _s;
};

#include <iostream>

int main()
{
    typedef std::vector<std::pair<std::string, Container> > my_vector;
    my_vector v;
    v.push_back(std::make_pair("Hello", Container(42)));
    v.push_back(std::make_pair("World", Container(1729)));
    my_vector::iterator i = std::find_if(v.begin(), v.end(), comp("World"));
    if (i != v.end())
    {
        Container& c = i->second;
        std::cout << c._c; // <== Prints 1729
    }
}

这是live example

【讨论】:

  • 现场示例的链接似乎已损坏
【解决方案2】:

使用Boost.RangeBoost.Bind,您可以这样做:

struct predicate
{
    template<class Key, class Pair>
    bool operator()(const Key& k, const Pair& p) const
    {
        return p.first == k;
    }
};

// Your vector of pairs
std::vector<std::pair<std:string, Container> v = ...;
// The key you would like to search for
std::string key = ...;
Container& c = boost::find_if(v, boost::bind(predicate(), key, _1))->second;

【讨论】:

  • 在这种情况下,可以将 boost::bind 替换为 std::bind1st 并以这种方式摆脱 boost。
【解决方案3】:

有一个简单的解决方案:使用std::copystd::inserter

#include <algorithm>
#include <map>
#include <string>
#include <utility> // pair
#include <vector>

void function()
{
    typedef int Data;
    typedef std::pair< std::string, Data > String_Data_Pair;
    typedef std::vector< String_Data_Pair > String_Data_Pair_Sequence;
    typedef std::map< std::string, Data > String_To_Data_Map;

    String_Data_Pair_Sequence string_data_pairs;

    /* fill 'string_data_pairs' here */

    String_To_Data_Map string_to_data_map;

    std::copy( string_data_pairs.begin(),
               string_data_pairs.end(),
               std::inserter( string_to_data_map,
                              string_to_data_map.begin() /* superfluous, but required */ ) );
}

【讨论】:

  • 你不能用String_To_Data_Map string_to_data_map(string_data_pairs.begin(), string_data_pairs.end());替换副本吗?
  • 是的……是的,你可以。我有时会忘记基于范围的构造函数。
【解决方案4】:
class SomeClass{
   int num;
public:
   SomeClass();
   void setNumber(int n) const { num = n;}
};

vector<pair<SomeClass,string> > vectr;

for(unsigned int i = 0; i < vectr.size(); i++)
   if(vectr[i].second == "key")
       vectr[i].first.setNumber(50);

为我工作!

【讨论】:

    猜你喜欢
    • 2013-08-18
    • 2011-01-01
    • 1970-01-01
    • 2019-02-05
    • 2011-10-29
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多