我试图在 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/