Chuyển tới nội dung chính

std::remove_copy_if

#include <algorithm>

template <class InputIterator, class OutputIterator, class UnaryPredicate>
OutputIterator remove_copy_if (InputIterator first, InputIterator last,
OutputIterator result, UnaryPredicate pred);

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, bỏ qua (không sao chép) các phần tử thỏa mãn một điều kiện cụ thể (được xác định bởi một hàm vị từ).

Tham số

first

  • Input Iterator trỏ đến phần tử đầu tiên trong phạm vi nguồn cần sao chép.

last

  • Input Iterator trỏ đến phần tử ngay sau phần tử cuối cùng trong phạm vi nguồn. Phạm vi nguồn là [first, last).

result

  • Output Iterator trỏ đến phần tử đầu tiên trong phạm vi đích nơi các phần tử sẽ được sao chép đến.

pred

  • Một hàm vị từ (unary predicate) nhận một đối số là phần tử trong phạm vi nguồn và trả về true nếu phần tử không được sao chép (thỏa mãn điều kiện để bị loại bỏ), false nếu phần tử được sao chép (không thỏa mãn điều kiện).

Giá trị trả về

  • Output Iterator trỏ đến phần tử ngay sau phần tử cuối cùng được sao chép trong phạm vi đích.

Đặc điểm

  1. Phạm vi nguồn [first, last) là "nửa mở", không bao gồm phần tử last.
  2. Phạm vi đích phải có đủ không gian để chứa các phần tử được sao chép. Sử dụng std::back_inserter là một cách an toàn khi sao chép vào container có thể thay đổi kích thước như std::vector.
  3. remove_copy_if() không thay đổi phạm vi nguồn.
  4. remove_copy_if() trả về iterator trỏ đến sau phần tử cuối cùng được sao chép trong phạm vi đích.
  5. 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.
  6. remove_copy_if() thường được sử dụng để:
    • Tạo một bản sao của một container, loại bỏ các phần tử thỏa mãn một tiêu chí nhất định (được định nghĩa bởi hàm vị từ).
    • Sao chép và lọc dữ liệu từ một nguồn sang một đích khác, chỉ giữ lại những dữ liệu đáp ứng một điều kiện cụ thể.
    • Kết hợp việc sao chép và lọc dữ liệu trong một bước duy nhất, thay vì phải thực hiện copy() sau đó remove_if().
Phân biệt với remove_if(), remove_copy(), và copy_if()
  • remove_if() di chuyển các phần tử "cần giữ lại" (không thỏa mãn điều kiện) lên đầu phạm vi, nhưng không thay đổi kích thước. Cần erase() để xóa phần thừa.
  • remove_copy() sao chép các phần tử không bằng với một giá trị cho trước sang phạm vi đích.
  • copy_if() chỉ sao chép các phần tử thỏa mãn điều kiện sang phạm vi đích.
  • remove_copy_if() sao chép các phần tử không thỏa mãn điều kiện (hàm vị từ) sang phạm vi đích.

Ví dụ

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

// Hàm vị từ kiểm tra số âm
bool isNegative(int n) {
return n < 0;
}

int main() {
std::vector<int> source = {1, -2, 3, -4, 5, -6, 7, 8, -9, 10};
std::vector<int> destination;

// Sao chép source sang destination, bỏ qua các số âm
std::remove_copy_if(source.begin(), source.end(), std::back_inserter(destination), isNegative);

std::cout << "destination after remove_copy_if: ";
for (int x : destination) {
std::cout << x << " ";
}
std::cout << std::endl;

std::string str = "This String Contains Some Vowels.";
std::string resultStr;

// Sao chép str sang resultStr, bỏ qua các nguyên âm (sử dụng lambda)
std::remove_copy_if(str.begin(), str.end(), std::back_inserter(resultStr),
[](char c){ return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'
|| c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U'; });

std::cout << "resultStr after remove_copy_if: " << resultStr << std::endl;

return 0;
}

Các hàm liên quan

removeDi 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
reverse_copySao 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 theo thứ tự đảo ngược
replace_copy_ifSao 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
countĐếm số lần xuất hiện của một giá trị cụ thể trong một phạm vi được chỉ định
copySao 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