有没有办法丢弃空捕获

Is There a Way to Discard Empty Captures?

本文关键字:有没有      更新时间:2023-10-16

是否有一种内置的方法可以只迭代非空捕获,或者我是否需要使用lambda/修改我的正则表达式?

例如,给定: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"));

当然,问题是我得到的输出是:

豌豆;胡萝卜

甜菜
披萨

Coleslaw

有办法绕过这个吗?

您可以使用std::copy_if和lambda来检查正则表达式匹配中的字符串是否为空。使用

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

实时示例

因为它只会打印非空字符串。

显而易见的方法是使用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(); } 
);

从那些比我聪明的人的回答来看,如果没有lambda,实际上似乎没有办法丢弃空结果。在这个问题上,有几个替代方案:

  1. 使用"向前看",这有点贵,但只捕捉没有"菠菜"的单词:
const regex re{ "(?:\s+|^)(?!Spinach)(\S+)" };
copy(sregex_token_iterator(cbegin(input), cend(input), re, 1), sregex_token_iterator(), ostream_iterator<string>(cout, "n"));

实时示例

  1. 使用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; });

实时示例

相关文章: