带有自定义比较器的 C++ std::find

Posted

技术标签:

【中文标题】带有自定义比较器的 C++ std::find【英文标题】:C++ std::find with a custom comparator 【发布时间】:2013-01-14 16:19:19 【问题描述】:

这基本上是我想做的:

bool special_compare(const string& s1, const string& s2)

    // match with wild card


std::vector<string> strings;

strings.push_back("Hello");
strings.push_back("World");

// I want this to find "Hello"
find(strings.begin(), strings.end(), "hell*", special_compare);

// And I want this to find "World"
find(strings.begin(), strings.end(), "**rld", special_compare);

但不幸的是,std::find 不能这样工作。那么只使用 STL,我怎么能做这样的事情呢?

【问题讨论】:

附注 - 比较中的字符串参数应该是 const string&amp; 而不仅仅是 string&amp;。顺便说一句,有趣的问题。 【参考方案1】:

根据您的 cmets,您可能正在寻找这个:

struct special_compare : public std::unary_function<std::string, bool>

  explicit special_compare(const std::string &baseline) : baseline(baseline) 
  bool operator() (const std::string &arg)
   return somehow_compare(arg, baseline); 
  std::string baseline;


std::find_if(strings.begin(), strings.end(), special_compare("hell*"));

【讨论】:

这正是我想要做的。【参考方案2】:

你需要使用的函数是这样的:std::find_if,因为std::find没有比较函数。

但是std::find_if 不带。您试图同时传递 valuecompare ,这让我感到困惑。不管怎样,看看documentation。看看用法的区别:

auto it1 = std::find(strings.begin(), strings.end(), "hell*");
auto it2 = std::find_if(strings.begin(), strings.end(), special_compare);

希望对您有所帮助。

【讨论】:

基本上我想将strings 中的每个字符串与"hell*" 进行比较,并将其与通配符匹配。所以它会找到“你好”。希望这更有意义。 @Josh:所以认为你需要find_if,你需要相应地实现compare函数。 我可能错了,但 compare 函数不只接受 1 个参数吗?我如何将它与我要查找的“hell*”字符串进行比较? @Josh:您可以在函数本身内部使用"hell*",无需传递给它。事实上,比较函数只接受一个参数。或者你可以使用函数对象,如果你想让它通用。【参考方案3】:

您需要std::find_if(),这很难使用,除非您使用的是 C++11 编译器。因为那时,您不需要硬编码要在某个比较器函数中搜索的值或实现仿函数对象,而是可以在 lambda 表达式中完成:

vector<string> strings;

strings.push_back("Hello");
strings.push_back("World");

find_if(strings.begin(), strings.end(), [](const string& s) 
    return matches_wildcard(s, "hell*");
);

然后你在某处写一个matches_wildcard()。

【讨论】:

Lambda 绝对是必经之路。没有理由为这样简单的事情创建一个完整的比较器类,尤其是在几乎每个人都拥有 C++11(+) 编译器的情况下。【参考方案4】:

因为还没有人提到std::bind,我就推荐这个

#include <functional>

bool special_compare(const std::string& s, const std::string& pattern)

    // match with wild card


std::vector<std::string> strings;
auto i = find_if(strings.begin(), strings.end(), std::bind(special_compare, std::placeholders::_1, "hell*"));

【讨论】:

bind 适用于 C++11,但可以避免在 C++11 上使用 lambda,如 @nikos-c 所述。【参考方案5】:

使用 C++11 lambda:

auto found = find_if(strings.begin(), strings.end(), [] (const std::string& s)  
    return /* you can use "hell*" here! */;
);

如果您不能使用 C++11 lambda,您可以自己创建一个函数对象。制作类型和重载运算符 ()。

【讨论】:

【参考方案6】:

我想举一个具有自定义查找逻辑的自定义类的示例,但没有找到类似的答案。所以我写了这个答案,它使用自定义比较器函数 (C++11) 来查找对象。

class Student 

private:  
  long long m_id;
  // private fields

public:
  long long getId()  return m_id; ;
  
;

现在假设,我想找到m_id 与给定ID 匹配的student 对象。我可以这样写std::find_if

// studentList is a vector array

long long x_id = 3; // local variable
auto itr = std::find_if(studentList.begin(), studentList.end(),
                    [x_id](Student& std_val) 
                     return std_val.getId() == x_id; 
                    );

if(itr == studentList.end())
  printf("nothing found");

【讨论】:

以上是关于带有自定义比较器的 C++ std::find的主要内容,如果未能解决你的问题,请参考以下文章

以模板为函数参数的 C++ 自定义比较函数

带有自定义比较器的 Linq 左外连接

C++ STL中SORT的自定义比较函数?

具有自定义比较器和 O(n) 时间的 priority_queue c++

如何仅通过向量对的第一个元素或自定义向量三元组使用 std::find?

具有自定义比较功能的 C++ 优先级队列在 Push() 上行为不正确