문제

내가 하려고 했 삭제 범위의 요소에서지도를 기반으로 특정 상태입니다.어떻게 그것을 사용하여 STL 알고리즘?

처음에는 나의 생각을 사용하여 remove_if 하지만 그것은 가능하지 않으로 remove_if 하지 않는 작업에 대한 연관 컨테이너입니다.

이 있"remove_if"해당하는 알고리즘을 작동까요?

으로 간단한 옵션을 생각 반복을 통해 지고 지울 수 있습니다.하지만 반복을 통해 지고 지우기 안전 옵션?(으로 반복기를 얻는 잘못된 후 삭제)

내가 사용하는 다음 예제:

bool predicate(const std::pair<int,std::string>& x)
{
    return x.first > 2;
}

int main(void) 
{

    std::map<int, std::string> aMap;

    aMap[2] = "two";
    aMap[3] = "three";
    aMap[4] = "four";
    aMap[5] = "five";
    aMap[6] = "six";

//      does not work, an error
//  std::remove_if(aMap.begin(), aMap.end(), predicate);

    std::map<int, std::string>::iterator iter = aMap.begin();
    std::map<int, std::string>::iterator endIter = aMap.end();

    for(; iter != endIter; ++iter)
    {
            if(Some Condition)
            {
                            // is it safe ?
                aMap.erase(iter++);
            }
    }

    return 0;
}
도움이 되었습니까?

해결책

다.

for(; iter != endIter; ) {
            if (Some Condition) {
                    aMap.erase(iter++);
            } else {
                    ++iter;
            }
}

당신이 원래 있던 것이 늘 반복기 두번 았다면 삭제는 요소에서 그것은;당신은 잠재적으로 건너 요소가 필요하다는 삭제됩니다.

이것은 일반적인 알고리즘을 나는 본 적이 사용하고 문서화에 많은 장소입니다.

[편집]당신은 올바른 것을 반복자는 무효화된 후 삭제하지만,반복기를 참조하는 요소를 삭제,다른 반복자들은 여전히 유효합니다.따라서 사용하 iter++에서 삭제()호출합니다.

다른 팁

std :: map (및 기타 컨테이너) 용 Erase_if

나는 이것에 대해 다음 템플릿을 사용합니다.

namespace stuff {
  template< typename ContainerT, typename PredicateT >
  void erase_if( ContainerT& items, const PredicateT& predicate ) {
    for( auto it = items.begin(); it != items.end(); ) {
      if( predicate(*it) ) it = items.erase(it);
      else ++it;
    }
  }
}

이것은 아무것도 반환하지는 않지만 std ::지도에서 항목을 제거합니다.

사용 예 :

// 'container' could be a std::map
// 'item_type' is what you might store in your container
using stuff::erase_if;
erase_if(container, []( item_type& item ) {
  return /* insert appropriate test */;
});

두 번째 예제 (테스트 값으로 전달할 수 있음) :

// 'test_value' is value that you might inject into your predicate.
// 'property' is just used to provide a stand-in test
using stuff::erase_if;
int test_value = 4;  // or use whatever appropriate type and value
erase_if(container, [&test_value]( item_type& item ) {
  return item.property < test_value;  // or whatever appropriate test
});

나는이 문서를 얻었다 우수한 SGI STL 참조:

MAP는 새로운 요소를지도에 삽입하는 것이 기존 요소를 가리키는 반복자를 무효화하지 않는 중요한 속성을 가지고 있습니다. 지도에서 요소를 지우는 것은 물론 지우는 요소를 가리키는 반복자를 제외하고는 반복자를 무효화하지 않습니다.

따라서 지워질 요소를 가리키는 반복자는 물론 무효화 될 것입니다. 다음과 같이하십시오 :

if (some condition)
{
  iterator here=iter++;
  aMap.erase(here)
}

원래 코드에는 하나의 문제 만 있습니다.

for(; iter != endIter; ++iter)
{
    if(Some Condition)
    {
        // is it safe ?
        aMap.erase(iter++);
    }
}

여기 iter For Loop에서 한 번 증가하고 Erase에서 또 다른 시간이 발생하며, 이는 아마도 일부 무한 루프로 끝날 것입니다.

지금, std::experimental::erase_if 헤더에서 사용할 수 있습니다 <experimental/map>.

보다: http://en.cppreference.com/w/cpp/experimental/map/erase_if

하단 노트에서 :

http://www.sgi.com/tech/stl/pairassociativecontainer.html

쌍 연관 컨테이너는 변이 가능한 반복기의 값 유형을 할당 할 수없고 쌍을 할당 할 수 없기 때문에 돌연변이 성 반복자 (사소한 반복자 요구 사항에 정의 된 바와 같이)를 제공 할 수 없습니다. 그러나, 쌍 연관 컨테이너는 완전히 일정하지 않은 반복기를 제공 할 수있다 : 식 (*i) .second = d가 유효하도록 반복자.

첫 번째

MAP는 새로운 요소를지도에 삽입하는 것이 기존 요소를 가리키는 반복자를 무효화하지 않는 중요한 속성을 가지고 있습니다. 지도에서 요소를 지우는 것은 물론 지우는 요소를 가리키는 반복자를 제외하고는 반복자를 무효화하지 않습니다.

둘째, 다음 코드가 좋습니다

for(; iter != endIter; )
{
    if(Some Condition)
    {
        aMap.erase(iter++);
    }
    else
    {
        ++iter;
    }
}

함수를 호출 할 때 매개 변수는 해당 함수를 호출하기 전에 평가됩니다.

따라서 ITER ++가 지우기 전에 ITER ++를 평가할 때, 반복자의 ++ 연산자는 현재 항목을 반환하고 호출 후 다음 항목을 가리 킵니다.

IMHO는 없습니다 remove_if() 동등한.
지도를 재정렬 할 수 없습니다.
그래서 remove_if() 당신이 전화 할 수있는 끝에 관심있는 쌍을 넣을 수 없습니다. erase().

기반 아이언 구주의 대답 STD 기능 복용 반복자의 라인을 따라 범위를 더 많이 제공하고자하는 사람들을 위해.

template< typename ContainerT, class _FwdIt, class _Pr >
void erase_if(ContainerT& items, _FwdIt it, _FwdIt _Last, _Pr _Pred) {
    for (; it != _Last; ) {
        if (_Pred(*it)) it = items.erase(it);
        else ++it;
    }
}

용기 품목을 잃어 버리고 반복자로부터 얻을 수있는 방법이 있는지 궁금합니다.

Steve Folly의 대답 더 효율적이라고 생각합니다.

여기 또 다른 것이 있습니다 쉽게 효율적인 솔루션:

솔루션이 사용됩니다 remove_copy_if 원하는 값을 새 컨테이너로 복사하려면 원래 컨테이너의 내용을 새 컨테이너의 내용과 교환합니다.

std::map<int, std::string> aMap;

...
//Temporary map to hold the unremoved elements
std::map<int, std::string> aTempMap;

//copy unremoved values from aMap to aTempMap
std::remove_copy_if(aMap.begin(), aMap.end(), 
                    inserter(aTempMap, aTempMap.end()),
                    predicate);

//Swap the contents of aMap and aTempMap
aMap.swap(aTempMap);

을 삭제하려는 경우에는 모든 요소와 키 보다 큰 2,그리고 가장 좋은 방법입니다

map.erase(map.upper_bound(2), map.end());

에 대해서만 작동 범위이지만,아니 어떤 조건이 있습니다.

나는 이렇게 사용합니다

 std::map<int, std::string> users;    
 for(auto it = users.begin(); it <= users.end()) {
    if(<condition>){
      it = users.erase(it);
    } else {
    ++it;
    }
 }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top