在Rcpp中用(西班牙语)重音单词排序映射
Sort map with (Spanish) accented words in Rcpp
通过在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"
我不知道如何在地图上做同样的事情:
// 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
将重音"árbol"放在"casa"之前,使用Rcpp甚至返回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 version 6.1.0 (clang-602.0.53)(基于LLVM 3.6.0svn)。关于我的Mac编译器缺少什么,我的Linux编译器有什么线索?
这是我的脚本和我的sessionInfo,对于两台机器:
// [[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
是没有意义的,因为映射总是排序,根据定义。该定义是模板实例化的具体类型的一部分。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++中显示实际值
- C++选择排序算法中的逻辑错误
- C++:对单词而不是数字进行快速排序
- 读取每个单词的文件,并使用二叉搜索树(词典)对这些单词进行排序
- 根据输入文本对单词进行排序,具体取决于重复多少次
- 如何根据第三个单词在文本文件中排序行
- C 简单字典:排序单词列表
- 按长度(单词)c++ 对字符串数组进行排序
- 对字符数组中的单词进行排序
- 对列表中最有可能由列表顶部的人说出的积极单词和列表末尾很少说出的单词进行排序
- 按字符串的矢量对大小写单词进行排序
- 排序这些单词的排序标准
- 为什么这个单词排序程序只循环一次?
- 我找到所有的单词,有五个字母在一个向量的字符串与equal_range,它一直抛出一个错误,说它没有排序
- 在Rcpp中用(西班牙语)重音单词排序映射
- 按字符串长度对单词排序
- 在c++中如何将单词排序到结构数组中
- c++查找首尾字母相同的单词,并按字母顺序对它们进行排序