删除2D矢量的元素

时间:2012-11-13 11:15:16

标签: c++ vector

我有一个2D矢量,我需要删除不包含足够值的块:

typedef vector<double> iniMatrix;


bool hasInsufficientEnergy() {
return true;
}
vector<double> Audio::filter(vector<iniMatrix>&blocks, double sumThres, double ZeroThres)
{
  vector<double> totalEnergy;
  vector<double> totalZeroCross;
  double totalSum = sumThres * blocks.size();
  double totalZero = ZeroThres * blocks.size();

  vector<iniMatrix> blockked;

  for(unsigned i=0; (i < blocks.size()); i++)
  {
    totalEnergy.push_back(abs(this->energy(blocks[i])));
    totalZeroCross.push_back(zerocross(blocks[i]));

    if(!totalEnergy[i] > totalSum || totalZeroCross[i] < ZeroThres)
    {
        hasInsufficientEnergy();
    }else{
        //hasInsufficientEnergy();
    }
    iniMatrix::iterator erase_after = remove_if(blocks[i].begin(), blocks[i].end(),
                                                &hasInsufficientEnergy);
 }
 }

问题是erase_after并出现错误消息:

In function ‘_OutputIterator std::remove_copy_if(_InputIterator, _InputIterator, 
 _OutputIterator, _Predicate) [with _InputIterator = __gnu_cxx::__normal_iterator<double*, 
std::vector<double, std::allocator<double> > >, _OutputIterator = 
__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, 
_Predicate = bool]’:
/usr/include/c++/4.2.1/bits/stl_algo.h:1302:   instantiated from ‘_ForwardIterator 
std::remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = 
__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, 
_Predicate = bool]’
Audio.cpp:105:   instantiated from here
/usr/include/c++/4.2.1/bits/stl_algo.h:1227: error: ‘__pred’ cannot be used as a function

任何人对我出错的地方都有任何想法吗?

3 个答案:

答案 0 :(得分:3)

std::remove_if的第三个参数是一个谓词函数(或任何可调用的实体),它接受一个元素,如果需要删除true则返回false如果不。向量的向量元素(或“2D向量”,就像你所说的那样)是一个向量,在你的情况下是vector<double>。这就是你的谓词的论点应该是:

bool HasInsufficientEnergy(const vector<double>& elem)
{
    // herein is the code that tests elem and decides
    // whether it should be removed or not
}

然后,您的filter()方法不应包含多于此内容

void Audio::filter(vector<iniMatrix>&blocks)
{
    auto it = std::remove_if(blocks.begin(), blocks.end(), &HasInsufficientEnergy);
    blocks.erase(it, blocks.end());
}

如果你的谓词需要aditional参数,那么将它实现为一个将它们作为构造函数参数的类。你也需要重载operator(),所以你有一个可调用的函子。 如果你的编译器支持C ++ 11,那么学习如何使用lambda函数,因为它们对于这个任务非常有用。

答案 1 :(得分:1)

remove_if和类似的算法,期望一个函数,而不是一个值,即你应该传递一个函数指针或函数double const &并返回bool

bool hasInsufficientEnergy(double const & element) {
    // return true if it should be removed, false otherwise
}

然后

iniMatrix::iterator erase_after = remove_if(blocks[i].begin(), blocks[i].end(), 
&hasInsufficientEnergy);

将起作用

答案 2 :(得分:1)

truefalse不是函数对象。如果你想使用remove_if,你必须给它一个指向函数或函数对象的指针,它将集合的成员作为参数并返回是否删除它。请查看std::remove_if

中的示例

AFAICS,您可以将remove_if/erase替换为if并将其简化为:

for(auto i=blocks.begin(); i != blocks.end(); )
{
    totalEnergy.push_back(abs(this->energy(*i)));
    totalZeroCross.push_back(zerocross(*i));

    if(!totalEnergy.rbegin() > totalSum || totalZeroCross.rbegin() < ZeroThres)
    {
        i = blocks.erase(i);
    } else {
        ++i;
    }
}