2014-10-03 9 views
6
bool xInItems = std::find(items.begin(), items.end(), x) != items.end(); 

Czy istnieje bardziej zwięzły sposób sprawdzenia, czy x jest w pozycji? Wydaje się to niepotrzebnie pełne (powtarzanie elementów trzy razy), co sprawia, że ​​intencja kodu jest trudniejsza do odczytania.C++ zwięzłe sprawdzanie, czy element w pojemniku STL (np. Wektor)

Na przykład, czy istnieje coś takiego jak następuje:

bool xInItems = boost::contains(items, x); 

Jeśli nie istnieje dowolny algorytm Boost/stl bardziej zwięzły, aby sprawdzić, czy kolekcja zawiera element, to jest uważane za dobre lub złe praktyki używać zamiast funkcji pomocnika, aby włączyć contains(items, x)?

Czy używam niewłaściwego pojemnika STL? Nawet zestaw std :: set spowodowałby, że bool xInItems = items.find(x) != items.end(); nadal wydaje się gadatliwy. Czy myślę o tym w niewłaściwy sposób?

+1

Dla 'std :: set', może' bool xInItems = (items.count (x) == 1); '. Dla reszty, 'boost :: find' jest prawdopodobnie najlepszym z możliwych. (W obu przypadkach STL i boost są "count()", ale nie są tak wydajne, ponieważ muszą przejść przez cały zakres). –

+3

Większość odpowiednich standardowych funkcji bibliotecznych zaprojektowano do pracy na parach iteratorów, a nie na całych kontenerach. Pozwala to na większą elastyczność kosztem zwięzłości. Na pewno możesz pisać swoje własne funkcje pomocnicze, jeśli chcesz (ja to robię), ale wtedy musisz umieścić ich nagłówki w dowolnym miejscu ... – dlf

+0

Jeśli ktoś mógłby wyjaśnić wielokrotne głosowania w dół, byłbym wdzięczny . Wciąż jestem stosunkowo nowy w publikowaniu na przepełnieniu stosu.Dzięki – JDiMatteo

Odpowiedz

1

Jeśli dane są sortowane, można użyć std::binary_search, która zwraca bool:

bool xInItems = std::binary_search(items.begin(), items.end(), x)); 

Jeśli naprawdę trzeba zostawić przedmioty un-sortowane, ale mam C++ 11 dostępne, może użyć std::any_of, ale wymaga predykatu, więc prawdopodobnie skończy się co najmniej tak szczegółowe, jak std::find (i prawdopodobnie bardziej).

+0

std :: binary_search zwraca bool, więc jest bardziej zwięzły, dlatego wybrałem tę odpowiedź nad innymi. Prawdziwe zabranie, chociaż myślę, to nie martwić się o zwięzłość par iteratorów, ponieważ para iteratorów to idiomatyczne C++. Nadal istnieje nadzieja, że ​​std :: range zostanie zaakceptowany w przyszłym standardzie, umożliwiając bardziej zwięzłe idiomatyczne C++. – JDiMatteo

0

Prostym sposobem na znalezienie jeśli element jest w zestawie znajduje się:

container.find(x) != container.end() 

tak, że jeśli jesteś w użyciu zbiór liczb całkowitych, to może być coś takiego:

stl::set<int> intSet; 
intSet.insert(3); 
if(intSet.find(3) != intSet.end()) 
     printf("Found it!"); 
+0

Już zasugerowałem std :: set find na moje pytanie. – JDiMatteo

0
#include "boost/range/algorithm/find.hpp" 

bool xInItems = boost::find(items, x) != items.end(); 

Jest to tak zwięzłe, jak należy się spodziewać, biorąc pod uwagę preferencje dotyczące elastycznego używania iteratora w C++.

Powinieneś po prostu trzymać się std :: find, ponieważ jest idiomatyczny i mam nadzieję, że ostatecznie std::range zostanie zaakceptowany i zapewni standardową, bardziej zwięzłą alternatywę dla par iteratorów.

4

Nie jest trudno napisać funkcję szablonu od zera.

template<typename T, typename Iterator> 
bool contains(Iterator it1, Iterator it2, const T & value) 
{ 
    return std::find(it1, it2, value) != it2; 
} 

template<typename T, typename Container> 
bool contains(const Container & c, const T & value) 
{ 
    return contains(c.begin(), c.end(), value); 
} 

Można nawet dostarczyć specjalizacje do pojemników, które mają swoje własne find funkcję tak, że nie dzwoni std::find.

+4

Aby uzyskać powyższą "przemysłową" siłę: zamień 'c.begin()' na 'using std :: begin;' w poprzednim wierszu i 'begin (c)' i uzyskasz magiczne wsparcie dla tablicy (wykonaj to samo dla ' .end() ') (C++ 11). Po drugie, uważam, że zwracanie wskaźnika do elementu (lub "opcjonalny") jest użyteczne - po rzutowaniu na 'bool' daje właściwą wartość i możesz zrobić' if (int * x = contains (vec, 3)) '(Używam' opcjonalnie '). Dodaj obsługę znaczników, aby podzielić asocjację z kontenerów sekwencji, aby użyć metody "find" z użyciem zbiorczych kontenerów zamiast wyszukiwania liniowego. – Yakk

+0

Nie było pytanie, jak napisać funkcję zawierającą szablony. Chodziło o to, czy istnieje już jedna w standardowej bibliotece lub doładowaniu, i czy pisanie siebie samego jest dobrą praktyką. Nadal daje +1, ponieważ jest to przydatne. – JDiMatteo

2

any_of_equal zrobi zadanie:

#include <boost/algorithm/cxx11/any_of.hpp> 

bool xInItems = boost::algorithm::any_of_equal(items, x);