【问题标题】:How to create a custom collator?如何创建自定义整理器?
【发布时间】:2016-03-11 04:59:08
【问题描述】:

我正在使用以下代码作为函数对字符串列表进行排序:

bool stringLessThan(const string& str1, const string& str2) 
{
   const collate<char>& col = use_facet<collate<char> >(locale()); // Use the global locale

   string s1(str1);
   string s2(str2);

   transform(s1.begin(), s1.end(), s1.begin(), ::tolower);
   transform(s2.begin(), s2.end(), s2.begin(), ::tolower);
   const char* pb1 = s1.data();
   const char* pb2 = s2.data();
   return (col.compare(pb1, pb1 + s1.size(), pb2, pb2 + s2.size()) < 0);
}

我将全局语言环境设置为:

locale::global(locale("pt_BR.UTF-8")); 

如果我使用en_EN.UTF-8 语言环境,我的语言(葡萄牙语-巴西)中带有口音的单词将按照我想要的不同顺序排列。所以我使用pt_BR.UTF-8。但是,字符串“as”在“a”之前,我想要“a”然后是“as”。

原因是整理器忽略了空格和字符串,如:

a pencil
an apple

将被视为:

apencil
anapple

如果已排序,将按以下顺序出现:

an apple
a pencil

但我想要:

a pencil
an apple

我用 Java 制作了这个,解决方案是创建一个自定义整理器。但是在 c++ 中我该如何处理呢?

【问题讨论】:

  • 我现在没有答案,但我有一个提示:如果您完全关心性能,则不应在比较函数中创建临时字符串。这些字符串的构造和复制将非常低效,如果您正在使用此比较功能,例如对于 std::map,比较器会被多次调用,从而导致效率低下。
  • 好的,我需要const。我能做些什么呢?
  • 在我的机器上 en_US.utf8pt_BR.utf8 似乎做同样的事情(他们忽略了这种情况,所以你的 tolower 转换是多余的)。
  • @n.m.我同意转型是多余的。但是en_US.UTF-8pt_BR.UTF-8 在使用重音时是不同的。尝试排序:TerrorSuspenseÉpico。会有所不同。
  • 它们对我的作用相同(Épico、Suspense、Terror)。我使用std::sort(v.begin(), v.end(), std::locale("en_US.utf8"));std::sort(v.begin(), v.end(), std::locale("pt_BR.utf8"));。它们不同于std::sort(v.begin(), v.end(), std::locale("C")); 你机器上的顺序是什么?

标签: c++ string sorting locale collation


【解决方案1】:

尝试创建自己的整理器类或比较函数。虽然在 Java 中,更惯用的方法可能是通过扩展来做到这一点,但在 c++ 中,对于您的情况,我建议使用组合。

这仅仅意味着您的自定义整理器类将具有一个整理器成员,用于帮助它执行整理,而不是从 collate 类派生。

至于您的比较规则,您似乎需要明确实现自己的逻辑。如果您不想忽略空格,也许您应该标记您的字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多