c++ - 查找数据集 C++ 模式的更好方法

标签 c++ math vector dictionary dataset

我试图在 C++ 中查找数据集的模式。我写了一个似乎可以做到这一点的函数,但我不喜欢在没有模式的情况下必须返回一个空 vector 。有没有更有效的方法来做到这一点?这是我的代码:

vector<double> findMode(vector<double> v)
{
    map<double, int> modeStorage;
    vector<double> mode;
    int mostRepetitions = 2;
    for (double i : v)
    {
        ++modeStorage[i];
    }
    for (map<double, int>::iterator it = modeStorage.begin(); it != modeStorage.end(); ++it)
    {
        if (it->second >= mostRepetitions)
        {
            mostRepetitions = it->second;
        }
    }
    for (map<double, int>::iterator it = modeStorage.begin(); it != modeStorage.end(); ++it)
    {
        if (it->second == mostRepetitions)
        {
          mode.push_back(it->first);
        }
    }
return mode;
}

提前致谢。

编辑:澄清一下:如果数据集中任何一个值中没有至少两个相同值,则没有模式。这就是为什么 mostRepetitions 必须 >= 2 的原因。如果函数发现没有模式(所有值在集合中只存在一次),那么它会返回一个空 vector 。那是我的问题。一旦我从函数中取回 vector ,我必须测试它是否为空,这对我来说很草率(如果不是,请告诉我,我会闭嘴)。

最佳答案

我用一些不同的方法做了一个片段: 1) 如果我们得到一个没有模式的 vector ,我们抛出一个异常。 2)我们只返回模式。 3)该函数是一个模板,但你可以用T代替适合您的类型。

我试图在评论中解释算法。

OBS:有一些 lambda 帮助我编写测试,它们需要 C++11 支持。如果您不知道或不知道,请关注 T findMode(const std::vector<T>& vec ) .

#include<vector>
#include<algorithm>
#include<string>
#include<stdexcept>

#include<iostream>


template<typename T>
T findMode(const std::vector<T>& vec ){

    if(vec.size() == 0){
        throw std::domain_error("No mode for empty vector");
    }
    else if(vec.size() == 1)
        return vec[0];

    // copy the original, don´t alter the input
    std::vector<T> v(vec); 

    // Order just to group same elements
    // T MUST implement '>' operator. Which is trivial
    // for primitive types.
    std::sort(v.begin(), v.end());  

    typename std::vector<T>::iterator it ; 

    it = v.begin(); 

    size_t largest_count = 0;
    T mode;
    bool flag = false; // this flag indicates when we found 2 equal modes
    while( it != v.end() ){

        T m = *it;
        size_t count = 1;

        while( it != v.end() && *++it == m ){   
            count++;            
        }   

        if(count > largest_count){
            largest_count = count;
            mode = m;
            flag = false;
        }
        else if(count == largest_count){
            flag = true;
        }
    }

    if(flag){
        // if we found a count as large as the largest, 
        // we have no made, so, throw exception
        throw std::domain_error("No mode for vector");
    }

    return mode;    
}

template<typename T>
bool test(const std::vector<T> v, const T& expected_mode){
    T mode;
    try{
        return findMode<T>(v) == expected_mode;
    }catch(const std::domain_error& de){
        return false;
    } 
}

int main(){


    const std::vector<int> vec_int = {1};
    std::cout << [&](){ return test<int>(vec_int, 1) == true ? "OK" : "NOK"; }() << " for {1}" 
        << std::endl;

    // This test is OK, if returns false, there is no mode
    const std::vector<int> vec_int2 = {1,1,2,2};
    std::cout << [&](){ return test<int>(vec_int2, 1) == false ? "OK" : "NOK"; }() 
        << " for {1,1,2,2}" << std::endl;

    // This test is OK, if returns false, there is no mode
    const std::vector<int> vec_int3 = {1,1,1,1};
    std::cout << [&](){ return test<int>(vec_int3, 1) == true ? "OK" : "NOK"; }() 
        << " for {1,1,1,1}" << std::endl;

    // This test is OK, if returns false, there is no mode
    const std::vector<double> vec_double = {6.25, 1.1, 1.1, 2.2, 2.3, 2.5, 6.25, 6.25, 6.25, 6};
    std::cout << [&](){ return test<double>(vec_double, 6.25) == true ? "OK" : "NOK"; }() 
        << " for {6.25, 1.1, 1.1, 2.2, 2.3, 2.5, 6.25, 6.25, 6.25, 6}" << std::endl;


    // This test is OK, if returns false, there is no mode
    const std::vector<char> vec_char ={'0', 'X', 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F'};
    std::cout << [&](){ return test<char>(vec_char, 'E') == true ? "OK" : "NOK"; }()
        << " for {'0', 'X', 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F'}" << std::endl;


    return 0;   
}

关于c++ - 查找数据集 C++ 模式的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21611431/

相关文章:

c++ - 带 Armadillo 的 Eclipse CDT 项目 - CDT 无法识别 'arma' 命名空间

c++ - 初始化列表与 vector

algorithm - 使用帕累托原则 (80/20),如果给定 0-100 之间的输入,如何计算真实百分比

vector - 使用 SVC 偏差结果可以得到非常大(或非常小的)特征向量值吗? [scikit-学习]

c++ - 无法将QWidget扩展的实例添加到QVector

c++ - 我的 'Person' 类有什么问题?

c++ - SDL2 全屏和渲染到纹理

python - Qt 和 PyQt 混合应用

excel - EXCEL的CUMIPMT函数的数学公式是什么(如何计算)?

mysql 算术运算(减法)最后一天的第一天(周,月)