简体   繁体   English

有没有办法丢弃空的捕获?

[英]Is There a Way to Discard Empty Captures?

Is there a built in way to iterate over non-empty captures only or do I need to use a lambda/modify my regex? 是否有内置的方法来迭代非空捕获或我是否需要使用lambda /修改我的正则表达式?

For example, given: const auto input = "Peas&Carrots Spinach-Casserole Beets Pizza Spinach-Salad Coleslaw"s I'd like to find foods that don't contain "Spinach". 例如,给定: const auto input = "Peas&Carrots Spinach-Casserole Beets Pizza Spinach-Salad Coleslaw"s我想找到包含“菠菜”的食物。 So I can do this: 所以我可以这样做:

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

The problem of course is that I get an output like: 问题当然是我得到的输出如下:

Peas&Carrots 豌豆和胡萝卜

Beets 甜菜
Pizza 比萨

Coleslaw 凉拌卷心菜

Is there a way around this? 有没有解决的办法?

The obvious way would be to use std::copy_if (or std::remove_copy_if ) and copy the string only if it's non-empty. 显而易见的方法是使用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(); } 
);

You can use std::copy_if and a lambda to check that the string from the regex match is empty or not. 您可以使用std::copy_if和lambda来检查正则表达式匹配中的字符串是否为空。 Using 运用

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

We get 我们得到了

Peas&Carrots
Beets
Pizza
Coleslaw

Live Example 实例

As it will only print non-empty strings. 因为它只会打印非空字符串。

From the answers of those wiser than I, it seems that there is in fact no way to discard empty results without a lambda. 从那些比我更聪明的答案中,似乎实际上没有办法在没有lambda的情况下丢弃空结果。 In this question there are a couple alternatives though: 在这个问题中,有几种选择:

  1. Use a Look Ahead, which is a bit more expensive, but only captures words without "Spinach": 使用前瞻,这有点贵,但只捕获没有“菠菜”的单词:
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. Use an istream_iterator and a lambda, this removes a lot of the flexibility of the lambda, but since input is white-space delimited this is probably the best option: 使用istream_iterator和lambda,这消除了lambda的很多灵活性,但由于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 实例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM