본문 바로가기

개발자/Algorithm

c++ STL 함수 remove, remove_if

반응형

<algorithm> 에 정의됨

 

안녕하세요.
오늘은 <algorithm> 헤더의 std::remove_if() 함수에 대해 알아보겠습니다.

template <class ForwardIterator, class T>
ForwardIterator remove(ForwardIterator first, ForwardIterator last,
                       const T& val);

template< class ForwardIt, class UnaryPredicate >
ForwardIt remove_if( ForwardIt first, ForwardIt last, UnaryPredicate p );

범위 내에 특정 값을 가진 원소들을 제거한다.

범위 (first 부터 last 전 까지) 내에 원소들 중에서 val 과 값이 일치하는 원소(remove)들 혹은 조건 p 를 만족하는 원소(remove_if)를 제거한 범위로 변환합니다. 이 때 이 함수는 해당 범위의 맨 끝을 가리키는 반복자를 리턴합니다.

 

참고로 이 함수는 실제로 원소를 제거하는 것이 아닙니다. 다만, 지워야 하는 원소들을 컨테이너 맨 뒤로 보내버릴 뿐입니다. 

 

즉, 위 함수가 리턴하는 반복자 부터 last 까지 원소들이 바로 val 과 일치하는 원소들로 대체됩니다. 따라서, 실제로 조건을 만족하는 원소들을 지워 버리기 위해서는 추가적으로 컨테이너들의 erase 함수를 호출해야 합니다.

 

지워지진 않은 원소들의 상대적 위치는 유지됩니다. 하지만, 지워질 원소들의 상대적 위치의 경우 유지됨이 보장되지 않습니다.

이 함수는 operator== 를 이용해서 원소를 비교합니다.

 

인자들

  • first, last : 원소의 시작과 끝을 가리키는 반복자들. 이 때 확인하는 범위는 [first, last)로 정의됩니다. 이들은 타입 T 와 비교 가능해야 하며 (operator== 로), 이동 가능해야만 합니다.
  • val : 삭제할 값
  • p : 원소를 한 개만 가지는 단항 함수로 p 의 리턴값은 bool 로 변환 가능해야만 합니다. 이 때, p 는 원소를 변경하면 안됩니다.

리턴값

지워지지 않은 마지막 원소 바로 뒤를 가리키는 반복자를 리턴한다. 즉 first 부터 이 함수가 리턴하는 반복자 바로 전 까지 val 과 일치하지 않는 원소들이 된다.

구현 예시

remove

template <class ForwardIt, class T>
ForwardIt remove(ForwardIt first, ForwardIt last, const T& value) {
  first = std::find(first, last, value);
  if (first != last)
    for (ForwardIt i = first; ++i != last;)
      if (!(*i == value)) *first++ = std::move(*i);
  return first;
}

remove_if

template <class ForwardIt, class UnaryPredicate>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p) {
  first = std::find_if(first, last, p);
  if (first != last)
    for (ForwardIt i = first; ++i != last;)
      if (!p(*i)) *first++ = std::move(*i);
  return first;
}

실행예제

#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>

int main() {
  std::string str1 = "Text with some   spaces";
  // 문자열에서 띄어쓰기를 모두 지운다.
  str1.erase(std::remove(str1.begin(), str1.end(), ' '), str1.end());
  std::cout << str1 << '\n';

  std::string str2 = "Text\n with\tsome \t  whitespaces\n\n";
  // 문자열에서 공백 문자 (띄어쓰기, 개행 문자 등등)를 지운다.
  str2.erase(std::remove_if(str2.begin(), str2.end(),
                            [](unsigned char x) { return std::isspace(x); }),
             str2.end());
  std::cout << str2 << '\n';
}

 

실행 결과

 

Textwithsomespaces

Textwithsomewhitespaces

반응형