std::remove_if
#include <algorithm>
template <class ForwardIterator, class UnaryPredicate>
ForwardIterator remove_if (ForwardIterator first, ForwardIterator last,
UnaryPredicate pred);
Di chuyển các phần tử không thỏa mãn điều kiện (được xác định bởi một hàm vị từ) lên đầu phạm vi, và trả về một iterator trỏ đến phần tử ngay sau phần tử cuối cùng của dãy mới (dãy không chứa các phần tử bị "xóa"). Các phần tử sau vị trí này đến cuối container sẽ có giá trị không xác định.
Tham số
first
- Forward Iterator trỏ đến phần tử đầu tiên trong phạm vi cần xóa.
last
- Forward Iterator trỏ đến phần tử ngay sau phần tử cuối cùng trong phạm vi cần xóa. Phạm vi là
[first, last)
.
pred
- Một hàm vị từ (unary predicate) nhận một đối số là phần tử trong phạm vi và trả về true nếu phần tử cần bị "xóa" (thỏa mãn điều kiện), false nếu không.
Giá trị trả về
- Forward Iterator trỏ đến phần tử ngay sau phần tử cuối cùng của dãy mới (dãy không chứa các phần tử bị "xóa").
Đặc điểm
remove_if()
không thay đổi kích thước của container. Nó chỉ di chuyển các phần tử.- Phạm vi
[first, last)
là "nửa mở", không bao gồm phần tửlast
. remove_if()
yêu cầu Forward Iterator, cho phép di chuyển một chiều về phía trước.- Để xóa thực sự các phần tử, bạn cần sử dụng phương thức
erase()
của container (như trong ví dụ). Đây được gọi là erase-remove idiom. - Các phần tử sau vị trí mà giá trị trả về của
remove_if()
trỏ tới cho đến cuối container sẽ có giá trị không xác định. - Trong C++11 trở lên, sử dụng biểu thức lambda cho hàm vị từ
pred
thường ngắn gọn và dễ đọc hơn. remove_if()
thường được sử dụng kết hợp với phương thứcerase()
của container để xóa thực sự các phần tử khỏi container (tương tự nhưremove()
). Đây cũng chính là erase-remove idiom.
Phân biệt với remove()
remove()
"xóa" các phần tử có giá trị bằng với một giá trị cho trước.remove_if()
"xóa" các phần tử thỏa mãn một điều kiện (hàm vị từ).
Ví dụ
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
// Hàm vị từ kiểm tra số chẵn
bool isEven(int n) {
return (n % 2) == 0;
}
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Di chuyển các số lẻ lên đầu, trả về iterator đến phần tử ngay sau số 9
auto it = std::remove_if(numbers.begin(), numbers.end(), isEven);
std::cout << "numbers after remove_if: ";
for (auto i = numbers.begin(); i != numbers.end(); ++i) {
std::cout << *i << " ";
}
std::cout << std::endl;
// Xóa các phần tử từ it đến cuối vector
numbers.erase(it, numbers.end());
std::cout << "numbers after erase: ";
for (int x : numbers) {
std::cout << x << " ";
}
std::cout << std::endl;
std::string str = "This string contains some vowels.";
// Xóa các nguyên âm, sử dụng lambda
str.erase(std::remove_if(str.begin(), str.end(),
[](char c){ return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'
|| c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U'; }),
str.end());
std::cout << "str after erase-remove_if: " << str << std::endl;
return 0;
}
Các hàm liên quan
remove | Di chuyển các phần tử không bị "xóa" lên đầu phạm vi, và trả về một iterator trỏ đến phần tử ngay sau phần tử cuối cùng của dãy mới |
remove_copy | Sao chép các phần tử từ một phạm vi (range) nguồn sang một phạm vi đích khác |
replace_if | Thay thế tất cả các phần tử trong một phạm vi (range) thỏa mãn một điều kiện cụ thể bằng một giá trị mới |
transform | Áp dụng một hàm (hoặc đối tượng hàm) cho mỗi phần tử trong một phạm vi (range) đầu vào và lưu trữ kết quả vào một phạm vi đầu ra |
find_if | Tìm kiếm phần tử đầu tiên trong một phạm vi thỏa mãn một điều kiện cụ thể được xác định bởi một hàm vị từ |