代码之家  ›  专栏  ›  技术社区  ›  F. Privé

特殊值不能作为无序映射中的键

  •  2
  • F. Privé  · 技术社区  · 6 年前

    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   
    

    如何仅为创建一个密钥 不适用 一个是为了 ?

    2 回复  |  直到 6 年前
        1
  •  6
  •   Ralf Stubner    6 年前

    bartop's idea 使用自定义的comperator是很好的,尽管特定的表单对我不起作用。所以我用 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是 不适用 只是一个 special form of an IEEE NaN .

        2
  •  5
  •   bartop    6 年前

    == 对任何事都是假的。所以,你不能这样做。您可以为 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);