特殊值不能用作unordered_map中的键

F. *_*ivé 2 c++ boost r rcpp

对于像NAor 这样的特殊值NaN,boost::unordered_map每次使用时都会创建一个新密钥insert.

// [[Rcpp::depends(BH)]]
#include <boost/unordered_map.hpp>
#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
void test_unordered_map(NumericVector vec) {

  boost::unordered_map<double, int> mymap;
  int n = vec.size();
  for (int i = 0; i < n; i++) {
    mymap.insert(std::make_pair(vec[i], i));
  }

  boost::unordered_map<double, int>::iterator it = mymap.begin(), end = mymap.end();
  while (it != end) {
    Rcout << it->first << "\t";
    it++;
  }
  Rcout << std::endl;
}

/*** R
x <- c(sample(10, 100, TRUE), rep(NA, 5), NaN) + 0
test_unordered_map(x)
*/
Run Code Online (Sandbox Code Playgroud)

结果:

> x <- c(sample(10, 100, TRUE), rep(NA, 5), NaN)

> test_unordered_map(x)
nan nan nan nan nan nan 4   10  9   5   7   6   2   3   1   8   
Run Code Online (Sandbox Code Playgroud)

如何只创建一个密钥NA和一个密钥NaN

Ral*_*ner 6

bartop使用自定义comperator的想法很好,虽然特定的形式对我不起作用.所以我用Boost的文档作为起点.结合R的合适功能我得到:

// [[Rcpp::depends(BH)]]
#include <boost/unordered_map.hpp>
#include <Rcpp.h>
using namespace Rcpp;

struct R_equal_to : std::binary_function<double, double, bool> {
  bool operator()(double x, double y) const {
    return (R_IsNA(x) && R_IsNA(y)) ||
      (R_IsNaN(x) && R_IsNaN(y)) ||
      (x == y);
  }
};

// [[Rcpp::export]]
void test_unordered_map(NumericVector vec) {

  boost::unordered_map<double, int, boost::hash<double>, R_equal_to> mymap;  
  int n = vec.size();
  for (int i = 0; i < n; i++) {
    mymap.insert(std::make_pair(vec[i], i));
  }

  boost::unordered_map<double, int>::iterator it = mymap.begin(), end = mymap.end();
  while (it != end) {
    Rcout << it->first << "\t";
    it++;
  }
  Rcout << std::endl;
}

/*** R
x <- c(sample(10, 100, TRUE), rep(NA, 5), NaN) + 0
test_unordered_map(x)
*/
Run Code Online (Sandbox Code Playgroud)

结果:

> x <- c(sample(10, 100, TRUE), rep(NA, 5), NaN) + 0

> test_unordered_map(x)
7   2   nan nan 4   6   9   5   10  8   1   3   
Run Code Online (Sandbox Code Playgroud)

如所希望的,NA并且NaN被插入一次.但是,在这个输出中无法区分它们,因为R NA只是IEEE NaN的一种特殊形式.


bar*_*top 5

根据IEEE标准,NaN值与==任何事物相比总是假的.所以,你不能这样做.您可以提供自己的比较器来unordered_map使用此std::isnan功能.

auto comparator = [](auto val1, auto val2) {
    return std::isnan(val1) && std::isnan(val2) || val1 == val2;
}
boost::unordered_map<double, int, boost::hash<double>, decltype(comparator)> mymap(comparator);
Run Code Online (Sandbox Code Playgroud)