2016-08-02 2 views
3

Есть ли встроенный способ перебора непустых захватов или мне нужно использовать лямбда/изменить мое регулярное выражение?Есть ли способ отказаться от пустых захватов?

Например, const auto input = "Peas&Carrots Spinach-Casserole Beets Pizza Spinach-Salad Coleslaw"s Я бы хотел найти продукты, которые не содержит содержит «Шпинат». Так что я могу сделать это:

const regex re{ "\\s*(?:\\S*Spinach\\S*|(\\S*))" }; 

copy(sregex_token_iterator(cbegin(input), cend(input), re, 1), sregex_token_iterator(), ostream_iterator<string>(cout, "\n")); 

Проблема, конечно, в том, что I get an output как:

Горох & Морковь

Свекла
Пицца

Coleslaw

Есть ли способ обойти это?

ответ

1

Вы можете использовать std::copy_if и лямбда, чтобы проверить, что строка из матча регулярного выражения является пустым или нет. Использование

copy_if(sregex_token_iterator(cbegin(input), cend(input), re, 1), 
     sregex_token_iterator(), ostream_iterator<string>(cout, "\n"), 
     [](const std::string& match){ return !match.empty(); }); 

Мы получаем

Peas&Carrots 
Beets 
Pizza 
Coleslaw 

Live Example

Как будет печатать только непустые строки.

1

Очевидным способом было бы использовать std::copy_if (или std::remove_copy_if) и скопировать строку, только если она не пуста.

remove_copy_if(
    sregex_token_iterator(cbegin(input), cend(input), re, 1), 
    sregex_token_iterator(), 
    ostream_iterator<string>(cout, "\n"), 
    [](string const &s) { return s.empty(); } 
); 
0

Из ответов тех, кто мудрее, чем я, кажется, что на самом деле нет способа сбросить пустые результаты без лямбда. В этом вопросе есть несколько альтернатив, хотя:

  1. Используйте Look Ahead, который немного дороже, но захватывает только слова без "Шпинат":
const regex re{ "(?:\\s+|^)(?!Spinach)(\\S+)" }; 

copy(sregex_token_iterator(cbegin(input), cend(input), re, 1), sregex_token_iterator(), ostream_iterator<string>(cout, "\n")); 

Live Example

  1. Используйте istream_iterator и лямбда, это удаляет большую гибкость лямбда, но с input бел-пробелами это, вероятно, самый лучший вариант:
istringstream{ input }; 

copy_if(istream_iterator<string>(cbegin(input), cend(input)), istream_iterator<string>(), ostream_iterator<string>(cout, "\n"), [](const auto& i) { return i.find("Spinach") == string::npos; }); 

Live Example

Смежные вопросы