2016-08-02 12 views
3

Gibt es eine integrierte Möglichkeit, nur über nicht leere Captures zu iterieren oder muss ich ein Lambda/modify my regex verwenden?Gibt es eine Möglichkeit, leere Erfassungen zu verwerfen?

Zum Beispiel, gegeben: const auto input = "Peas&Carrots Spinach-Casserole Beets Pizza Spinach-Salad Coleslaw"s Ich möchte Lebensmittel finden, die nicht enthalten enthalten "Spinat". So kann ich dies tun:

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

Das Problem ist natürlich, dass I get an output wie:

Erbsen & Karotten

Beets
Pizza

Coleslaw

Gibt es einen Weg dazu?

Antwort

1

Sie können std::copy_if und ein Lambda überprüfen verwenden, dass die Zeichenfolge aus dem Regex leer sind oder nicht. Mit

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

Wir bekommen

Peas&Carrots 
Beets 
Pizza 
Coleslaw 

Live Example

Da es nur nicht-leere Zeichenfolgen gedruckt werden.

1

Der offensichtliche Weg wäre, std::copy_if (oder std::remove_copy_if) zu verwenden und die Zeichenfolge nur zu kopieren, wenn sie nicht leer ist.

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

Aus den Antworten derer, die klüger sind als ich, scheint es tatsächlich keine Möglichkeit zu geben, leere Ergebnisse ohne Lambda zu verwerfen. obwohl in dieser Frage gibt es ein paar Alternativen:

  1. einen Blick Verwenden Ahead, die etwas teurer ist, aber nur fängt also ohne "Spinat":
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. Verwenden Sie eine istream_iterator und ein Lambda, das entfernt viel von der Flexibilität des Lambda, aber seit input ist weiß-Raum begrenzt ist dies wahrscheinlich die beste Option:
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