对于NA
或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)
*/
结果:
> 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
如何仅为NA
创建一个密钥,为NaN
创建一个密钥?
答案 0 :(得分:6)
bartop's idea很好,尽管特定的格式对我不起作用。因此,我以Boost's documentation为起点。结合合适的functions from 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)
*/
结果:
> 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
根据需要,NA
和NaN
仅插入一次。但是,由于R的NA
只是special form of an IEEE NaN,因此无法在此输出中区分它们。
答案 1 :(得分:5)
根据IEEE标准,与==
相比,NaN值始终等于false。因此,您就是不能这样做。您可以使用此std::isnan
函数为unordered_map
提供自己的比较器。
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);