2017-12-21 14 views
2

나는 일반적으로 쓰는 많은 코드가 "이 컨테이너를 통해 반복하고 일부 조건과 일치하는 요소에 대해 X"패턴을 따르고 있음을 확인합니다. 종종 다음과 같습니다일치하는 요소를위한 루프 for clean

는 :

std::vector<int> theList(10); 
std::iota(theList.begin(), theList.end(), 0); 

for (auto i : theList) 
{ 
    if ((i % 2) == 0) 
    { 
     //Do something with i 
    } 
} 

나는이 경우에 if 문을 좋아하지 않는다 - 그들은 못생긴 정말 루프의 논리에 무슨 일이 일어나고 있는지에서 떨어지다.

내가 원하는 것은 문제를 해결할 수있는 더 좋은 방법이므로 문제의 핵심은 멋지게 표현됩니다. 그것은이 패턴 같은 느낌

std::vector<int> theList(10); 
std::iota(theList.begin(), theList.end(), 0); 

auto criteria = [](const int& i) -> bool { return (i % 2) == 0; }; 

for (auto it = std::find_if(theList.begin(), theList.end(), criteria); 
    it != theList.end(); 
    it = std::find_if(++it, theList.end(), criteria) 
    ) 
{ 
    std::cout << *it << ", "; 
} 

가 청소기 방법으로 std::algorithm에 그것의 방법을 확인해야합니다 :

내 최고의 시도는 지금까지 모두 좋은하지 않습니다.

더 좋은 방법이 있나요?

+0

'있다 std :: remove_if'를 사용하여 다른 언어의'filter' 고차 함수와 같은리스트를 필터링합니다. 그러나 필터링 된 목록에는 별도의 메모리가 저장되어야합니다. – Gassa

답변

1

당신은이에 대한 간단한 고차 함수를 만들 수 있습니다

template <typename Range, typename Predicate, typename F> 
void for_items_matching(Range&& r, Predicate&& p, F&& f) 
{ 
    for(auto&& x : r) 
    { 
     if(p(x)) { f(x); } 
    } 
} 

사용 예 : 일부 리팩토링 및 헬퍼 클래스/기능으로

auto criteria = [](const int& i) -> bool { return (i % 2) == 0; }; 
for_items_matching(theList, criteria, [](auto&& item) 
{ 
    std::cout << item << ", "; 
}) 

당신이 뭔가 끝낼 수를 like :

for_items_of(theList) 
    .matching(criteria) 
    .execute([](auto&& item){ std::cout << item << ", "; }); 

또 다른 가능성은 다가오는 Ranges TS입니다.

+0

감사합니다. 이것은 현재 우리가 할 수있는 최선의 방법 인 것 같습니다. 아래의 @ vlad-from-moscow에 대한 비슷한 대답 (두 가지를 모두 사용 하리라 생각합니다.) 그러나 처음에는 대답을 얻었습니다 :) – fwgx

1

내가 올바르게 이해했다면 표준 알고리즘 std::for_each_if이 필요합니다. 예를 들어

#include <iostream> 
#include <iterator> 
#include <numeric> 

template<class InputIterator, class Predicate, class Function> 
Function for_each_if(InputIterator first, 
        InputIterator last, 
        Predicate predicate, 
        Function f) 
{ 
    for (; first != last; ++first) 
    { 
     if (predicate(*first)) f(*first); 
    } 

    return f; 
} 

int main() 
{ 
    int a[10]; 

    std::iota(std::begin(a), std::end(a), 0); 

    for_each_if(std::begin(a), std::end(a), 
     [](int x) { return x % 2 == 0; }, 
     [](int x) { std::cout << x << ", "; }); 

    std::cout << std::endl; 

    return 0; 
} 

프로그램 출력은

0, 2, 4, 6, 8, 

그러나 실제로 내가 표준에 포함하는 제안을했다하지만 C++에서 이러한 알고리즘의 표준은 없다. :)