2015-07-19 16 views
5

Trong khi tôi có thể từ thành công loại Tây Ban Nha với nguyên âm có dấu bằng cách xác định một locale UTF-8 trong std :: sắp xếp,Sắp xếp với (Tây Ban Nha) có dấu từ trong 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; 
} 

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

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

tôi không thể tìm ra cách cũng làm như vậy với một bản đồ:

// 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 

Bất kỳ ý tưởng về làm thế nào để có table_words đặt dấu "Arbol" trước khi "casa", với Rcpp hoặc thậm chí trở lại trong R, với base::sort?

Ngoài ra, std::sort(..., std::locale("en_US.UTF-8")) chỉ các từ trên máy Linux của tôi với: gcc phiên bản 4.8.2 (Ubuntu 4.8.2-19ubuntu1). Nó không hoạt động trên Mac 10.10.3 với: Apple LLVM phiên bản 6.1.0 (clang-602.0.53) (dựa trên LLVM 3.6.0svn). Bất kỳ manh mối nào về trình biên dịch Mac của tôi bị thiếu mà trình biên dịch Linux của tôi có?

Dưới đây là kịch bản của tôi và sessionInfo tôi, cho cả máy:

// [[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 
+1

Pardon sự thiếu hiểu biết của tôi, nhưng khi đã làm 'std :: sort' mất một tham số thứ ba đó là một miền địa phương? Tham số thứ ba cho 'std :: sort' được coi là một hàm hoặc hàm functor so sánh hai mục, không phải là một ngôn ngữ. – PaulMcKenzie

+1

@PaulMcKenzie: Một ngôn ngữ là, trong số những thứ khác, một functor so sánh hai mục. http://en.cppreference.com/w/cpp/locale/locale/operator() –

+1

Không biết gì về "Rcpp", nhưng bạn có biết rằng đối với một 'std :: map', thứ tự là một phần của loại chính nó và bạn cần một bộ so sánh tùy chỉnh để kích hoạt một thứ tự khác? –

Trả lời

1

Nó không có ý nghĩa để áp dụng std::sort trên std::map, vì bản đồ luôn được sắp xếp, theo định nghĩa. Định nghĩa đó là một phần của loại bê tông được khởi tạo bởi khuôn mẫu. std::map có thông số loại "ẩn" thứ ba cho hàm so sánh được sử dụng để đặt các khóa, mặc định là std::less cho loại khóa. Xem http://en.cppreference.com/w/cpp/container/map.

Trong trường hợp của bạn, bạn có thể sử dụng std::locale làm loại so sánh và vượt qua std::locale("en-US") (hoặc bất kỳ điều gì phù hợp với hệ thống của bạn) với hàm tạo.

Đây là một ví dụ. Nó sử dụng C++ 11, nhưng bạn có thể dễ dàng sử dụng cùng một giải pháp trong 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"; 
    } 
} 

Output:

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

Tất nhiên, bạn phải nhận thức được thực tế là std::locale là cao thực hiện phụ thuộc. Bạn có thể tốt hơn với Boost.Locale.

Một vấn đề khác là giải pháp này có thể trông khó hiểu, bởi vì một số std::locale không chính xác là điều mà nhiều lập trình viên sẽ liên kết với một hàm so sánh. Nó gần như quá thông minh.

Do đó một sự thay thế có thể dễ đọc hơn:

#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"; 
    } 
} 
+0

Cảm ơn bạn đã trợ giúp mở rộng, nhưng vẫn không có may mắn: Earls-MBP: C++ earlbrown $ 'g ++ -std = C++ 11 order_with_accents.cpp -o go' Earls-MBP: C++ earlbrown $'./Go' 'collate_byname :: collate_byname không thể xây dựng cho en-US' Earls-MBP: C++ earlbrown $' g ++ -v' 'Cấu hình với: --prefix =/Applications/Xcode.app/Contents/Developer/usr - with-gxx-include-dir =/usr/include/C++/4.2.1 Phiên bản Apple LLVM 6.1.0 (clang-602.0.53) (dựa trên LLVM 3.6.0svn) Mục tiêu: x86_64-apple-darwin14.4.0 Mô hình chủ đề: posix' –

Các vấn đề liên quan