2016-12-22 5 views
7

std :: map에서 첫 번째 (최저 키) N 개 항목을 삭제하는 메소드를 작성하려고합니다. 시도 :std :: map에서 처음 N 개의 항목을 지우시겠습니까?

제거 할 요청 된 수보다 많은 요소가있을 때 작동합니다. 따라서 5 개의 요소가 있고 2를 삭제하도록 요청하면 마지막 세 요소가 유지됩니다. 그러나 하나의 요소가 있고 2를 지우도록 요청한 경우 하나의 요소가 남아 있습니다.

이것을 덮을 수있는 깔끔한 방법이 있습니까? mapEize()보다 큰 numElementsToRemove를 확인하는 IF 문을 밀어 낼 수 있지만 더 좋은 해결책이 있어야합니까?

+4

왜 가장 간단한 해결책보다 나은 해결책이 있을까요? –

답변

4

std::advance(i, n)은 적어도 n 번 증가 될 수있는 전제 조건을 가지고 있습니다. 코드에서 해당 전제 조건을 확인하지 않으므로 numElementsToRemove > originalSize으로 호출하면 해당 전제 조건을 위반하여 정의되지 않은 동작이 발생합니다. 이 문제를 해결하려면, 당신은 아마도 std::min를 사용하여 std::advance를 호출하기 전에 검사를 수행해야합니다

if (originalSize <= numElementsToRemove) { 
    auto eraseIter = _map.begin(); 
    std::advance(eraseIter, numElementsToRemove); 

    _map.erase(_map.begin(), eraseIter); 
} else { 
    _map.clear(); // or whatever's appropriate 
} 
4

if 문은 간단한 읽을 솔루션을 제공합니다 std::next과 if 문을 사용하는 것이 좋습니다. 그 _map.size() < numElementsToRemove이 기호/서명 불일치를 가지고 있지만

void EraseNMapElements(const int numElementsToRemove) 
{ 
    if (_map.size() < numElementsToRemove) 
     _map.erase(_map.begin(), std::next(_map.begin(), numElementsToRemove)); 
    else 
     _map.clear(); 
} 

주의 마십시오. numElementsToRemovestd::size_t 또는 decltype(_map)::size_type이어야합니다.

1

가장 간단한 방법은 내가이 일을 볼 수 있습니다

auto realNumToRemove = std::min(numElementsToRemove, originalSize); 
std::advance(eraseIter, realNumToRemove); 
2

아직 언급되지 않았지만 좋은 점은 C++ 11 std :: map :: erase (const_iterator)가 실제로 다음 요소에 반복자를 반환하기 때문입니다.

auto i = _map.begin(); 
while (i != _map.end() && numElementsToRemove > 0) 
{ 
    i = _map.erase(i); 
    --numElementsToRemove; 
} 

이가 삭제 한 번이 아닌 두 번하는 요소를 통과합니다 : 그래서 코드도 같이 쓸 수 있습니다.

+2

참. 동시에 다중 요소 '지우기'가 필요할 때마다 한 번에 삭제하는 것과 비교하여 필요한 균형 조정 작업의 수를 크게 줄이는 것이 가능할 수도 있습니다. 언제나처럼 : 공연을 고려할 때, 측정하십시오. – Angew