std::set 使用 boost::iequals 进行自定义字符串比较

发布于 2025-01-11 09:27:40 字数 469 浏览 0 评论 0原文

以下代码运行良好,没有问题,但想知道是否可以使用 boost::iequals 重写自定义比较运算符,该运算符可以在不转换为上位的情况下进行比较。

std::string copyToUpper(std::string s)
{
    std::transform(s.begin(),s.end(),s.begin(),::toupper);
    return s;   
}

struct caseInsensitiveCompare {
    bool operator() (const std::string& a, const std::string& b) const {
        return (copyToUpper(a).compare(copyToUpper(b)) < 0);
    }
};
std::set<std::string, caseInsensitiveCompare> keys;

Following code works well without issues but wondering, if it is possible to rewrite custom comparison operator using boost::iequals , which compares without converting to upper.

std::string copyToUpper(std::string s)
{
    std::transform(s.begin(),s.end(),s.begin(),::toupper);
    return s;   
}

struct caseInsensitiveCompare {
    bool operator() (const std::string& a, const std::string& b) const {
        return (copyToUpper(a).compare(copyToUpper(b)) < 0);
    }
};
std::set<std::string, caseInsensitiveCompare> keys;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

£冰雨忧蓝° 2025-01-18 09:27:40

我会像这样定义一个比较器:

#include <boost/algorithm/string/predicate.hpp>

struct ci_compare {
    bool operator()(std::string_view const& a,
                    std::string_view const& b) const {
        return boost::ilexicographical_compare(a, b);
    }
};

然后您可以将它与您选择的数据结构一起使用:

std::set<std::string, ci_compare> keys;

Live On Compiler Explorer

#include <boost/algorithm/string/predicate.hpp>

struct ci_compare {
    bool operator()(std::string_view const& a,
                    std::string_view const& b) const {
        return boost::ilexicographical_compare(a, b);
    }
};

#include <boost/core/demangle.hpp>
#include <fmt/ranges.h>
#include <map>
#include <set>
using namespace std::string_literals;

auto dump(auto const& data) {
    fmt::print("---\nData structure: {}\nData: {}\nContains 'three'? {}\n",
            boost::core::demangle(typeid(data).name()), data,
            data.contains("three"));
}

int main() {
    dump(std::set{{"hellO", "hEllo", "world"}, ci_compare{}});

    dump(std::map<std::string, int, ci_compare>{
        std::pair{"one"s, 1}, {"TWO"s, 2}, {"Three", 3}});
}

打印

---
Data structure: std::set<char const*, ci_compare, std::allocator<char const*> >
Data: {"hellO", "world"}
Contains 'three'? false
---
Data structure: std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, ci_compare, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >
Data: {("one", 1), ("Three", 3), ("TWO", 2)}
Contains 'three'? true

I would define a comparator like this:

#include <boost/algorithm/string/predicate.hpp>

struct ci_compare {
    bool operator()(std::string_view const& a,
                    std::string_view const& b) const {
        return boost::ilexicographical_compare(a, b);
    }
};

Then you can use it with your datastructure of choice:

std::set<std::string, ci_compare> keys;

Live On Compiler Explorer

#include <boost/algorithm/string/predicate.hpp>

struct ci_compare {
    bool operator()(std::string_view const& a,
                    std::string_view const& b) const {
        return boost::ilexicographical_compare(a, b);
    }
};

#include <boost/core/demangle.hpp>
#include <fmt/ranges.h>
#include <map>
#include <set>
using namespace std::string_literals;

auto dump(auto const& data) {
    fmt::print("---\nData structure: {}\nData: {}\nContains 'three'? {}\n",
            boost::core::demangle(typeid(data).name()), data,
            data.contains("three"));
}

int main() {
    dump(std::set{{"hellO", "hEllo", "world"}, ci_compare{}});

    dump(std::map<std::string, int, ci_compare>{
        std::pair{"one"s, 1}, {"TWO"s, 2}, {"Three", 3}});
}

Prints

---
Data structure: std::set<char const*, ci_compare, std::allocator<char const*> >
Data: {"hellO", "world"}
Contains 'three'? false
---
Data structure: std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, ci_compare, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >
Data: {("one", 1), ("Three", 3), ("TWO", 2)}
Contains 'three'? true
淡紫姑娘! 2025-01-18 09:27:40

几乎所有 STL 容器都依赖于严格的弱排序。因此,比较函数需要返回的不是字符串是否彼此相等,而是字符串中的一个“小于”另一个。但是 boost::iequals 检查相等,如果一个字符串比另一个字符串“小”,则不相等,因此不能将它用于映射、集合或排序函数的比较器。

Almost all STL containers rely on strict weak ordering. So the comparison function needs to return, not whether the strings are equal to each other, but that one is "less" than the other. But boost::iequals checks for equality and not if one string is "less" than the other, so you can't use it for the comparator of a map, a set or a sort function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文