2012-11-13 3 views
1

나는 2 차원 벡터를 가지고 있고 충분한 값을 포함하지 않는 블록을 제거해야합니다제거 요소

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 

누구나 내가 잘못 가고있는 곳으로 아이디어가 있습니까?

+0

왜 에너지와 제로 십자가를 벡터에 저장합니까? 이전 값은 사용하지 않습니다. 지금까지 모든 블록에서 총 에너지를 합한 것입니까? –

답변

1

true 또는 false는 함수 객체없는 작동합니다. remove_if을 사용하려면 컬렉션의 멤버를 매개 변수로 사용하여 제거할지 여부를 반환하는 함수 또는 함수 객체에 대한 포인터를 지정해야합니다. , std::remove_if

AFAICS의 예를 봐 당신은 ifremove_if/erase를 교체하고 그것을 단순화 수 : 그 문제에 관해서,

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; 
    } 
} 
+0

하지만 그건 그냥 값을 지 웁니다 .. 나는 실제로 블록을 제거해야하므로 2D 벡터가 더 작습니다. 크기를 다시 조정할 수 있습니까? – Phorce

+0

@Phorce'resize()'는 할당 해제를 보장하지 않습니다. 빈 벡터로'swap()'을해야한다. –

+0

'hasInsufficientEnergy'는'true' 나'false'가 아닌 함수입니다. –

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); 

을 반환

+0

내가 내 원래의 게시물의 코드 인수를 필요 @Phorce, 그것은 – Phorce

+0

작동하지 않습니다를 업데이트 한 함수는 – Pieter

+0

왜 보았다되는 목록에서 요소의 내용 인'더블 CONST 및'인수를 가지고 요소가 아니라 블록? 나는 이중 요소가 통과 해야하는 것을 얻지 못합니까 ?? – Phorce

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()); 
} 

보다 훨씬 더 많은 것을 포함하는 클래스로 구현 안되는 이것을 생성자 매개 변수로 사용합니다. 호출 가능 펑터 (funable functor)를 가질 수 있도록 operator()을 오버로드해야합니다. 컴파일러에서 C++ 11을 지원하는 경우 람다 함수를 사용하는 방법을 배우십시오.이 함수는이 작업에 매우 유용하므로이 기능을 사용하십시오.