C++ 将double分类为任意存储箱

C++ 将double分类为任意存储箱,c++,algorithm,boost,stl,C++,Algorithm,Boost,Stl,我正在寻找一个类,它可以将浮点数分类到任意容器中。垃圾箱。所需的语法如下: std::vector<double> bin_vector; // ..... fill the vector with 1, 1.4, 5, etc not evenly spaced values Binner bins(bin_vector); for (std::vector<double>::const_iterator d_itr = some_vector.begin();

我正在寻找一个类,它可以将浮点数分类到任意容器中。垃圾箱。所需的语法如下:

std::vector<double> bin_vector;

// ..... fill the vector with 1, 1.4, 5, etc not evenly spaced values

Binner bins(bin_vector); 

for (std::vector<double>::const_iterator d_itr = some_vector.begin(); 
     d_itr != some_vector.end(); d_itr++) { 
  int bin = bins.categorize(*d_itr); 

  // bin would be 0 for x < 1, 1 for 1 < x < 1.4, etc
  // do something with bin
}
std::vector bin_vector;
// ..... 用1、1.4、5等间距不均匀的值填充向量
宾纳箱(宾纳矢量);
for(std::vector::const_迭代器d_itr=some_vector.begin();
d_itr!=某个向量.end();d_itr++{
int bin=分类箱(*d_itr);
//对于x<1,bin为0,对于1

不幸的是,由于可移植性的要求,我仅限于boost和stl。我已经使用映射推出了我自己的O(logn)解决方案,重载
使用std::map,将间隔边界映射到bin编号。然后使用.upper_bound()查找箱子。

使用std::map,将间隔边界映射到箱子编号。然后使用.upper_bound()来查找箱子。

这里有一个未经测试的通用算法,它接受任意长度M的输入向量和N-1个箱子边界的排序向量,并返回N个箱子计数的向量。Bin i计算区间[breaks[i-1],breaks[i]中的值。T1和T2类型应相互可比。复杂性等于O(M*log(N))

\include//std::已排序,std::下界
#包括//断言
#包含//标准::距离
#include//std::vector
样板
标准::矢量箱计数(常数标准::矢量和输入,常数标准::矢量和中断)
{
//breaks是一个排序向量-INF=breaks.back()){
//[aN-1,+INF]中的最后一个箱子计数值
++输出[N-1];
打破
}
const auto break_it=std::下限(breaks.begin()、breaks.end()、*it);
bin_index=std::距离(breaks.begin(),break_it)+1;
++输出[bin_索引];
}
返回输出;
}

这是一个未经测试的通用算法,它采用任意长度M的输入向量和N-1个存储单元边界的排序向量,并返回N个存储单元计数的向量。存储单元i对间隔[breaks[i-1],breaks[i]中的值进行计数。类型T1和T2应相互比较。复杂性等于O(M*log(N))

\include//std::已排序,std::下界
#包括//断言
#包含//标准::距离
#include//std::vector
样板
标准::矢量箱计数(常数标准::矢量和输入,常数标准::矢量和中断)
{
//breaks是一个排序向量-INF=breaks.back()){
//[aN-1,+INF]中的最后一个箱子计数值
++输出[N-1];
打破
}
const auto break_it=std::下限(breaks.begin()、breaks.end()、*it);
bin_index=std::距离(breaks.begin(),break_it)+1;
++输出[bin_索引];
}
返回输出;
}

你能对向量进行排序吗?
还有,哪个操作更关键,是构建
Binner
还是查找?@BjörnPollex是的,你可以对向量进行排序Boost邮件列表上有一个关于这一点的线程:建议的解决方案是使用std::accumultive来收集bin内容。@KillianDS任何范围都是sep根据
bin_vector
中的值,可以将
向量的索引指定为bin赋值,并且每个bin的大小为
1
?(另外:您应该更清楚地了解所需的输出)你能对向量进行排序吗?还有,哪个操作更重要,是构建
Binner
还是查找?@BjörnPollex是的,你可以对向量进行排序Boost邮件列表中有一个线程:建议的解决方案是使用std::accumulate来收集bin内容。@KillianDS任何分隔的范围通过
bin_vector
中的值,可以将
向量的索引指定为bin赋值,并且每个bin的大小为
1
?(另外:您应该更清楚地了解所需的输出)啊,是的,看起来它会工作,也似乎很明显。不确定为什么我以前没有看到那个函数。啊,是的,看起来它会工作,也似乎很明显。不确定为什么我以前没有看到那个函数。
#include<algorithm>     // std::is_sorted, std::lower_bound
#include<cassert>       // assert
#include<iterator>      // std::distance
#include<vector>        // std::vector

template<typename T1, typename T2>
std::vector<std::size_t> bin_count(const std::vector<T1>& input, const std::vector<T2>& breaks)
{
    // breaks is a sorted vector -INF < a0 < a1 < ... < aN-2 < +INF
    assert(std::is_sorted(breaks.begin(), breaks.end()));
    auto N = breaks.size() + 1;

    std::vector<std::size_t> output(N, 0);

    if (N == 1) {
        // everything is inside [-INF, INF)
        output[0] = input.size();
        return output;
    }

    for(auto it = input.begin(), it != input.end(); ++it) {
        if (*it < breaks.front()) {
            // first bin counts values in [-INF, a0)
            ++output[0];
            break;
        }
        if (*it >= breaks.back()) {
            // last bin counts values in [aN-1, +INF)
            ++output[N-1];
            break;
        }

        const auto break_it = std::lower_bound(breaks.begin(), breaks.end(), *it);
        bin_index = std::distance(breaks.begin(), break_it) + 1;
        ++output[bin_index];
    }

    return output;  
}