草庐IT

c++ - 在 Rcpp 中用(西类牙语)重音词对 map 进行排序

coder 2024-02-05 原文

虽然我可以通过在 std::sort 中指定 UTF-8 语言环境来成功地对带有重音元音的西类牙语单词进行排序,

// [[Rcpp::export]]
std::vector<std::string> sort_words(std::vector<std::string> x) {
  std::sort(x.begin(), x.end(), std::locale("en_US.UTF-8"));
  return x;
}

/*** R
words <- c("casa", "árbol", "zona", "árbol", "casa", "libro")
sort_words(words)
*/

returns (as expected):
[1] "árbol" "árbol" "casa"  "casa"  "libro" "zona"

我不知道如何用 map 做同样的事情:

// slightly modified version of tableC on http://adv-r.had.co.nz/Rcpp.html
// [[Rcpp::export]]
std::map<String, int> table_words(CharacterVector x) {
  std::setlocale(LC_ALL, "en_US.UTF-8");
  // std::setlocale(LC_COLLATE, "en_US.UTF-8"); // also tried this instead of previous line
  std::map<String, int> counts;
  int n = x.size();
  for (int i = 0; i < n; i++) {
    counts[x[i]]++;
  }
  return counts;
}

/*** R
words <- c("casa", "árbol", "zona", "árbol", "casa", "libro")
table_words(words)
*/

returns:
casa    libro   zona    árbol
    2       1       1       2

but I want:
árbol   casa    libro   zona    
    2       2       1       1

关于如何让 table_words 使用 Rcpp 将带重音的“árbol”放在“casa”之前,或者甚至在 R 中使用 base::sort 退出,有什么想法吗?

此外,std::sort(..., std::locale("en_US.UTF-8")) 在我的 Linux 机器上只有文字:gcc 版本 4.8.2(Ubuntu 4.8.2-19ubuntu1)。它不适用于 Mac 10.10.3:Apple LLVM 版本 6.1.0 (clang-602.0.53)(基于 LLVM 3.6.0svn)。关于我的 Mac 编译器缺少而我的 Linux 编译器有什么的任何线索?

对于两台机器,这是我的脚本和我的 session 信息:

// [[Rcpp::plugins(cpp11)]]
#include <locale>
#include <clocale>
#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
std::vector<std::string> sort_words(std::vector<std::string> x) {
  std::sort(x.begin(), x.end(), std::locale("en_US.UTF-8"));
  return x;
}

// [[Rcpp::export]]
std::map<String, int> table_words(CharacterVector x) {
  // std::setlocale(LC_ALL, "en_US.UTF-8"); // tried this instead of next line
  std::setlocale(LC_COLLATE, "en_US.UTF-8");
  std::map<String, int> counts;
  int n = x.size();
  for (int i = 0; i < n; i++) {
    counts[x[i]]++;
  }
  return counts;
}

/*** R
words <- c("casa", "árbol", "zona", "árbol", "casa", "libro")
sort_words(words)
table_words(words)
sort(table_words(words), decreasing = T)
output_from_Rcpp <- table_words(words)
sort(names(output_from_Rcpp))
*/

> words <- c("casa", "árbol", "zona", "árbol", "casa", "libro")

> sort_words(words)
[1] "árbol" "árbol" "casa"  "casa"  "libro" "zona" 

> table_words(words)
 casa libro  zona árbol 
    2     1     1     2 

> sort(table_words(words), decreasing = T)
 casa árbol libro  zona 
    2     2     1     1 

> output_from_Rcpp <- table_words(words)

> sort(names(output_from_Rcpp))
[1] "árbol" "casa"  "libro" "zona" 

sessionInfo on linux machine:
R version 3.2.0 (2015-04-16)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 14.04 LTS

locale:
[1] en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] tools_3.2.0 Rcpp_0.11.6

sessionInfo on Mac:
R version 3.2.1 (2015-06-18)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.10.3 (Yosemite)

locale:
[1] en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] textcat_1.0-3 readr_0.1.1   rvest_0.2.0  

loaded via a namespace (and not attached):
 [1] httr_1.0.0    selectr_0.2-3 R6_2.1.0      magrittr_1.5  tools_3.2.1   curl_0.9.1    Rcpp_0.11.6   slam_0.1-32   stringi_0.5-5
[10] tau_0.0-18    stringr_1.0.0 XML_3.98-1.3 

最佳答案

std::map 上应用 std::sort 没有意义,因为 ma​​p 总是排序,根据定义。该定义是模板实例化的具体类型的一部分。 std::map 具有第三个“隐藏”类型参数,用于用于对键进行排序的比较函数,键类型默认为 std::less。参见 http://en.cppreference.com/w/cpp/container/map .

在你的情况下,你可以使用 std::locale 作为比较类型,并传递 std::locale("en-US") (或任何合适的你的系统)到构造函数。

这是一个例子。它使用 C++11,但您可以在 C++03 中轻松使用相同的解决方案。

#include <map>
#include <iostream>
#include <string>
#include <locale>
#include <exception>

using Map = std::map<std::string, int, std::locale>;

int main()
{
    try
    {
        Map map(std::locale("en-US"));
        map["casa"] = 1;
        map["árbol"] = 2;
        map["zona"] = 3;
        map["árbol"] = 4;
        map["casa"] = 5;
        map["libro"] = 6;

        for (auto const& map_entry : map)
        {
            std::cout << map_entry.first << " -> " << map_entry.second << "\n";
        }
    }
    catch (std::exception const& exc)
    {
        std::cerr << exc.what() << "\n";
    }
}

输出:

árbol -> 4
casa -> 5
libro -> 6
zona -> 3

当然,您必须意识到 std::locale 高度依赖于实现这一事实。 Boost.Locale 你可能会过得更好.

另一个问题是这个解决方案可能看起来令人困惑,因为 std::locale 并不是许多程序员会与比较函数相关联的东西。这几乎有点太聪明了。

因此一个可能更具可读性的替代方案:

#include <map>
#include <iostream>
#include <string>
#include <locale>
#include <exception>

struct ComparisonUsingLocale
{
    std::locale locale{ "en-US" };

    bool operator()(std::string const& lhs, std::string const& rhs) const
    {
        return locale(lhs, rhs);
    }
};

using Map = std::map<std::string, int, ComparisonUsingLocale>;

int main()
{
    try
    {
        Map map;
        map["casa"] = 1;
        map["árbol"] = 2;
        map["zona"] = 3;
        map["árbol"] = 4;
        map["casa"] = 5;
        map["libro"] = 6;

        for (auto const& map_entry : map)
        {
            std::cout << map_entry.first << " -> " << map_entry.second << "\n";
        }
    }
    catch (std::exception const& exc)
    {
        std::cerr << exc.what() << "\n";
    }
}

关于c++ - 在 Rcpp 中用(西类牙语)重音词对 map 进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31498002/

有关c++ - 在 Rcpp 中用(西类牙语)重音词对 map 进行排序的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - 在 Ruby 中用键盘诅咒数组浏览 - 2

    我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作

  3. ruby-on-rails - 标准化文件名的字符串,删除重音和特殊字符 - 2

    我正在尝试找到一种方法来规范化字符串以将其作为文件名传递。到目前为止我有这个:my_string.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.gsub(/[^a-z]/,'_')但第一个问题:-字符。我猜这个方法还有更多问题。我不控制名称,名称字符串可以有重音符、空格和特殊字符。我想删除所有这些,用相应的字母('é'=>'e')替换重音符号,并将其余的替换为'_'字符。名字是这样的:“Prélèvements-常规”“健康证”...我希望它们像一个没有空格/特殊字符的文件名:“prelevements_routin

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  6. ruby-on-rails - 需要帮助最大化多个相似对象中的 3 个因素并适当排序 - 2

    我需要用任何语言编写一个算法,根据3个因素对数组进行排序。我以度假村为例(如Hipmunk)。假设我想去度假。我想要最便宜的地方、最好的评论和最多的景点。但是,显然我找不到在所有3个中都排名第一的方法。Example(assumingthereare20importantattractions):ResortA:$150/night...98/100infavorablereviews...18of20attractionsResortB:$99/night...85/100infavorablereviews...12of20attractionsResortC:$120/night

  7. ruby-on-rails - 在具有 ActiveRecord 条件的相关模型中按字段排序 - 2

    我正在尝试按Rails相关模型中的字段进行排序。我研究的所有解决方案都没有解决如果相关模型被另一个参数过滤?元素模型classItem相关模型:classPriority我正在使用where子句检索项目:@items=Item.where('company_id=?andapproved=?',@company.id,true).all我需要按相关表格中的“位置”列进行排序。问题在于,在优先级模型中,一个项目可能会被多家公司列出。因此,这些职位取决于他们拥有的company_id。当我显示项目时,它是针对一个公司的,按公司内的职位排序。完成此任务的正确方法是什么?感谢您的帮助。PS-我

  8. ruby - 在 ruby​​ 中使用 .try 函数和 .map 函数 - 2

    我需要从json记录中获取一些值并像下面这样提取curr_json_doc['title']['genre'].map{|s|s['name']}.join(',')但对于某些记录,curr_json_doc['title']['genre']可以为空。所以我想对map和join()使用try函数。我试过如下curr_json_doc['title']['genre'].try(:map,{|s|s['name']}).try(:join,(','))但是没用。 最佳答案 你没有正确传递block。block被传递给参数括号外的方法

  9. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  10. ruby - 按数字(从大到大)然后按字母(字母顺序)对对象集合进行排序 - 2

    我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby​​做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排

随机推荐