2010-11-19 4 views
15

Gibt es einen STL/Boost-Algorithmus, der prüft, ob alle Elemente zwischen zwei Iteratoren mit einem bestimmten Wert übereinstimmen? Oder alternativ, dass ein Prädikat für alle von ihnen true zurückgibt?Gibt es einen STL/Boost-Algorithmus, um alle Elemente in einem Container auf einen Wert zu überprüfen?

das heißt so etwas wie

template<class InputIterator, class T> 
InputIterator all_match (InputIterator first, InputIterator last, const T& value) 
{ 
    bool allMatch = true; 
    while(allMatch && first!=last) 
     allMatch = (value == *first++); 
    return allMatch; 
} 

Oder

template <class InputIterator, class Predicate> 
bool all_true (InputIterator first, InputIterator last, Predicate pred) 
{ 
    bool allTrue = true; 
    while (allTrue && first != last) 
     allTrue = pred(*first++); 
    return allTrue; 
} 

Antwort

22

Wenn Sie das Prädikat negieren können Sie std :: find/std :: find_if verwenden können und sehen, ob es das Ende Element Ihrer Sequenz zurückgibt. Wenn nicht, gibt es dasjenige zurück, das übereinstimmt.

Sie können eine Funktion mit std :: not1 oder std :: not_equal_to anpassen, indem Sie sie mit std :: find_if kombinieren, indem Sie STL verwenden, ohne eine Schleife zu schreiben.

bool allMatch = seq.end() == std::find_if(seq.begin(), seq.end(), 
    std::not_equal_to(val)); 
bool allPass = seq.end() == std::find_if(seq.begin(), seq.end(), 
    std::not1(pred)); 
+0

Das wird gut tun. Vielen Dank. – GrahamS

+4

eigentlich glaube ich nicht, dass 'not_equal_to()' Syntax ist ganz richtig. Ich könnte etwas falsch machen, aber ich musste 'bind2nd' damit verwenden:' std :: find_if (seq.begin(), seq.end(), std :: bind2nd (std :: not_equal_to () , val)) ' – GrahamS

2

könnten Sie std: Finden Sie ord std :: find_if dies zu tun.

template <class T> 
struct pred { 
    T t_; 

    pred(const T& value) : t_(value) {} 

    bool operator()(const T &t) 
    { 
     return t != t_; 
    } 
}; 

if (e.cend() == std::find_if(c.cbegin(), c.cend(), pred<T>(value))) 
    print("all match value"); 
+0

Wie ich es verstehe, finden und find_if nur die erste Übereinstimmung in einem Container finden. Ich möchte überprüfen, dass jedes Element zwischen den Iteratoren ein gegebener Wert ist. – GrahamS

+0

Zeigt meine Bearbeitung, wie es funktionieren soll? – frast

+0

Entschuldigung, mein Prädikat war worng. Ich habe es jetzt korrigiert. – frast

2

Sie können std::equal mit dem Prädikat verwenden. Etwas wie:

using namespace std; 
using namespace boost::lambda; 

int main() 
{ 
    vector<int> a; 
    a.push_back(1); 
    a.push_back(1); 
    a.push_back(2); 
    a.push_back(2); 
    a.push_back(3); 
    bool allMatch = equal(a.begin(), a.begin() + 2, a.begin(), _1 == 1); 
    return 0; 
} 
18

C++ 0x führt std::all_of ein.

+0

@avakar: Abschnitt 25.1 [algorithms.general] Es führt auch' std :: any_of' und 'std :: none_of' (und die berüchtigte' std :: copy_if') ein. –

+0

@avakar: Wir verwenden nicht C++ 0x, aber das ist nützlich, um trotzdem zu wissen, danke. – GrahamS

+0

Das ist interessant. Es zeigt, dass C++ 0x eine Verschiebung hin zu einer humaneren Schnittstelle darstellt. – wilhelmtell

1

Oft kann man sich nur zählen:

template<class FwdIterator, class T> 
InputIterator all_match (FwdIterator first, FwdIterator last, const T& value) 
{ 
    return std::count(first, last, value) == std::distance(first, last); 
} 

Ineffiziente, wenn der Iterator nicht zufällig ist, oder wenn es false zurück. Funktioniert nicht für Eingabe-Iteratoren.

+0

Stoppt auch nicht, sobald es eine Nichtübereinstimmung findet, die es für sehr große Behälter weniger ideal macht. – GrahamS

Verwandte Themen