2012-11-23 13 views
12

Bir vektörü filtrelemeye çalışıyorum, bu nedenle yalnızca belirli bir değer içeriyor.Bir yüklemeye ek bir parametre iletebilir misiniz?

örn. Vektörün yalnızca "abc" değerinin öğelerini içerdiğinden emin olun.

Şu an bunu remove_copy_if ile elde etmeye çalışıyorum.

Std'nin algoritmalarından birini kullanırken bir yüklemeye ek bir parametre iletmenin herhangi bir yolu var mı?

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); 

Ben bir yüklem olarak aşağıdaki işlevi geçmesine umuyorum ama bu sadece remove_copy_if ve sonraki tarafından muayene ediliyor geçerli değerini karşılaştırarak sona ereceğini daha muhtemel görünüyor.

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

Bu yanlış anladığım için bir fikrim var, bu nedenle herhangi bir öneriniz için teşekkür ederiz!

Teşekkür

+0

Sadece merak - sadece bir vektörü ne için kullanıyorsunuz? – Zane

+0

Örneğimi olabildiğince basit hale getirmeye çalıştım, bu yüzden anlamlı oldu :) Bu konuda yaptığım şey, belirli bir desene (regex ile) uyan bir vektörün elemanlarını kaldırmaktı. – noko

cevap

16

ile

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")); 

Örnek yerine functor tanımlama

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

Not çıkışı olduğu vektör, second, remove_copy_if() çağrısı önce öğeler olmalıdır:

// 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); 

funktor yüklemler kopyalanır gibi daha çaba copied_items bilgileri korumak için gereklidir. Önerilen çözümler için bkz. Pass std algos predicates by reference in C++.

+0

Bu çözümü kullanmaya çalıştığımda "tanımsız bir referans" ile ilgili bir hata görüyorum, neler olabileceğine dair bir fikir var mı? – noko

+0

@noko, kodu ideone veya benzerlerine gönderebilir misiniz? Derleyicinin C++ 11 lambdas'ı desteklemesi gerektiğini unutmayın (g ++ 'da -std = C++ 0x 'derleyici anahtarını kullanmanız gerekir). – hmjd

+0

boşver, fonksiyondan önce bir ClassName :: eklemeyi unuttum :( – noko

8

Yap funktoru veya std/boost::bind kullanın.

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")); 

veya C++ 11 kullanım halinde bir lambda: bağlama

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"));