c++ - 使用 std::find 在 std::map 中进行不区分大小写的搜索

标签 c++ algorithm dictionary stdmap

我需要通过不区分大小写的比较从 vector 列表中找到字符串。有没有不使用 Boost 的简单解决方案?

我为区分大小写的搜索编写的代码是:

std::map<std::string, std::string>::const_iterator it;
if (map.end() != (it = map.find(mKey)))
    // if word matches

根据一个答案的建议,我使用了 find_if 并得到了以下异常。它在特定值下给出以下错误

 my_map1["$$HYPHEN{{a"] = "-"; 

enter image description here

尝试使用 lexicographical_compare 的代码:

std::map<std::string, std::string> map1;
std::map<std::string,
         std::string,
         bool(*)(const std::string&, const std::string&)>
     my_map_temp(case_insensitive_string_cmp);
my_map_temp["$$HYPHEN--a"] = "foo";
my_map_temp["$$HYPHEN{{a"] = "foo1";
while (my_map_temp.end() !=  my_map_temp.find("$$HYPHEn--a"))
    {
       std::cout << my_map_temp["hellOOOO"] << std::endl;
    }

但在这种情况下,如何将 map1 值复制到 my_map_temp

最佳答案

std::map::find 依赖于 map 的内部排序。如果要使用此方法进行搜索,则需要使用不区分大小写的比较功能构建 map ,也就是说,不区分大小写的 WRT 键的 map 。

这可以通过利用 std::lexicographical_compare 轻松完成。算法,将其与不区分大小写的元素比较:

#include <cctype>
#include <algorithm>
#include <string>

bool case_insensitive_cmp(char lhs, char rhs)
{
  return std::toupper(lhs) < std::toupper(rhs);
}

bool case_insensitive_string_cmp(const std::string& lhs, 
                                 const std::string& rhs)
{
  return std::lexicographical_compare(lhs.begin(), 
                                      lhs.end(),
                                      rhs.begin(),
                                      rhs.end(),
                                      case_insensitive_cmp);
}

然后,使用不区分大小写的字符串比较函数创建映射:

std::map<std::string, 
         std::string, 
         bool(*)(const std::string&, const std::string&)> 
     my_map(case_insensitive_string_cmp);

my_map["Helloooo"] = "foo";
my_map["HELLOOOO"] = "bar";
std::cout << my_map["hellOOOO"] << std::endl;

Live demo .

如果您希望您的 map 具有标准的、区分大小写的行为,但又想执行不区分大小写的搜索,那么您需要使用 std::find_if用一个合适的谓词。但是在这里你失去了 map 的 O(logN) 查找的优势。

这是在标准 map 中进行不区分大小写搜索的工作示例。在 C++11 中会更简洁:

#include <map>
#include <iostream>
#include <cctype>
#include <algorithm>
#include <string>

bool case_insensitive_eq(const char& lhs, const char& rhs)
{
    return std::toupper(lhs) == std::toupper(rhs);
}

bool case_insensitive_string_eq(const std::string& lhs, const std::string& rhs)
{
  return std::equal(lhs.begin(), 
                    lhs.end(),
                    rhs.begin(),
                    case_insensitive_eq);
}

typedef std::map<std::string, std::string> StringMap;

struct case_insensitive_key_eq
{
  case_insensitive_key_eq(const std::string& key) : key_(key) {}

  bool operator()(StringMap::value_type item) const
  {
    return case_insensitive_string_eq(item.first, key_);
  }
  std::string key_;
};

int main()
{
  StringMap my_map;

  my_map["Helloooo"] = "foo";
  StringMap::iterator it = std::find_if(my_map.begin(), 
                                        my_map.end(), 
                                        case_insensitive_key_eq("HeLlOOoo"));
  if (it != my_map.end())
  {
    std::cout << "Found element " << it->second << std::endl;
  } else
  {
    std::cout << "element not found\n";
  }
}

关于c++ - 使用 std::find 在 std::map 中进行不区分大小写的搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23153967/

相关文章:

c# - 带委托(delegate)或开关的字典?

python - 使用带冒号的字符串创建字典

c++ - 改进替代解析器的使用

c++ - Visual Studio 错误 D8016 : '/ZI' and '/O2' command-line options are incompatible

c++ - 在C++中更新函数之间的变量

c++ - 使模板参数成为模板类的友元

java - 矩形可挠度的最小周长

java - 比较两个列表并获取子对象

algorithm - 在未排序的数组中找到 2 个等于给定总和的数字

python - 将点分隔的字符串解析为字典变量