2012-11-23 26 views
12

Tôi đang cố gắng lọc một vectơ để nó chỉ chứa một giá trị cụ thể.Bạn có thể chuyển một tham số bổ sung cho vị từ không?

ví dụ: Đảm bảo rằng vectơ chỉ chứa các phần tử của giá trị "abc".

Hiện tại, tôi đang cố gắng đạt được điều này với remove_copy_if.

Có cách nào để chuyển một tham số bổ sung cho một biến vị ngữ khi sử dụng một trong các thuật toán của std không?

std::vector<std::string> first, second; 
first.push_back("abc"); 
first.push_back("abc"); 
first.push_back("def"); 
first.push_back("abd"); 
first.push_back("cde"); 
first.push_back("def"); 

std::remove_copy_if(first.begin(), first.end(), second.begin(), is_invalid); 

tôi hy vọng để vượt qua các chức năng sau đây như một vị nhưng có vẻ như nhiều khả năng rằng điều này sẽ chỉ kết thúc so sánh giá trị hiện tại được kiểm tra bởi remove_copy_if và tiếp theo.

bool is_invalid(const std::string &str, const std::string &wanted) 
{ 
    return str.compare(wanted) != 0; 
} 

Tôi có cảm giác mình có thể tiếp cận sai điều này nên mọi đề xuất sẽ được đánh giá cao!

Cảm ơn

+0

Chỉ cần tự hỏi - bạn sử dụng một vector chỉ với các phần tử giống hệt nhau để làm gì? – Zane

+0

Tôi đã cố gắng làm cho ví dụ của mình càng đơn giản càng tốt để nó có ý nghĩa :) Những gì tôi đã làm với điều này là để loại bỏ các phần tử từ một vectơ phù hợp với một mẫu nhất định (với regex). – noko

Trả lời

16

Xác định một functor thay vì:

struct is_invalid 
{ 
    is_invalid(const std::string& a_wanted) : wanted(a_wanted) {} 
    std::string wanted; 
    bool operator()(const std::string& str) 
    { 
     return str.compare(wanted) != 0; 
    } 
}; 

std::remove_copy_if(first.begin(), 
        first.end(), 
        second.begin(), 
        is_invalid("abc")); 

hoặc nếu C++ 11 sử dụng một lambda:

std::string wanted("abc"); 
std::remove_copy_if(first.begin(), first.end(), second.begin(), 
    [&wanted](const std::string& str) 
    { 
     return str.compare(wanted) != 0; 
    }); 

Lưu ý rằng đầu ra vectơ, second, phải có yếu tố trước khi cuộc gọi đến remove_copy_if():

// Create 'second' after population of 'first'. 
// 
std::vector<std::string> second(first.size()); 

std::string wanted = "abc"; 
int copied_items = 0; 
std::remove_copy_if(first.begin(), first.end(), second.begin(), 
    [&wanted, &copied_items](const std::string& str) -> bool 
    { 
     if (str.compare(wanted) != 0) return true; 
     copied_items++; 
     return false; 
    }); 
second.resize(copied_items); 

Như các vị từ functor được sao chép nỗ lực nhiều hơn là cần thiết để giữ lại thông tin copied_items. Xem Pass std algos predicates by reference in C++ để biết các giải pháp được đề xuất.

+0

Tôi dường như gặp lỗi về "tham chiếu không xác định" khi tôi cố gắng sử dụng giải pháp này, bất kỳ ý tưởng nào về những gì có thể xảy ra? – noko

+0

@ noko, bạn có thể đăng bạn mã lên ideone hoặc tương tự không? Lưu ý rằng trình biên dịch phải hỗ trợ C++ 11 lambdas (trong g ++ bạn cần sử dụng '-std = C++ 0x' trình biên dịch). – hmjd

+0

không bao giờ nhớ, tôi quên thêm một ClassName :: trước khi chức năng: ( – noko

8

Làm functor hoặc sử dụng std/boost::bind.

struct is_invalid 
{ 
public: 
    is_invalid(const std::string& w):wanted(w) { } 
    bool operator() (const std::string& str) 
    { 
     return str.compare(wanted) != 0; 
    } 
private: 
    std::string wanted; 
}; 

std::remove_copy_if(first.begin(), first.end(), second.begin(), is_invalid("abc")); 

Ví dụ với ràng buộc

bool is_invalid(const std::string &str, const std::string &wanted) 
{ 
    return str.compare(wanted) != 0; 
} 

std::remove_copy_if(first.begin(), first.end(), second.begin(), 
boost::bind(is_invalid, _1, "abc")); 
Các vấn đề liên quan