从std::string中删除特定的连续字符重复

4

也许有人有一种高效的方法来删除特定字符的连续重复项,最好使用内置字符串操作,而不是显式地遍历字符串字符。

例如,当我有通配符模式并且只想删除连续星号(*)时:
/aaaa/***/bbbb/ccc/aa/*****/dd --> /aaaa/*/bbbb/ccc/aa/*/dd

对于所有字符的重复重复项,我可以使用std::unique以以下方式:

str.erase( std::unique(str.begin(), str.end()), str.end());

但是对于仅特定字符,该怎么办。


你可以使用正则表达式替换,但在这种情况下自己编写可能会更好。 - Cruz Jean
1
使用带有可变lambda的std::remove_if函数,然后跟随erase()函数。就是这么简单。 - Sam Varshavchik
@SamVarshavchik 这个保证元素被连续访问吗? - François Andrieux
根据 cppreference 的说法,它是这样的。 - Sam Varshavchik
@SamVarshavchik 你能提供链接吗?我没找到。编辑:我猜算法接受前向迭代器,所以如果你传递其中之一,你保证连续访问。我很困扰的是我找不到明确说明。如果你传递一个随机访问迭代器,我不明白为什么它不能执行谓词的无序评估。特别是因为该算法接受“ExecutionPolicy”,这意味着它似乎旨在支持多线程。 - François Andrieux
1个回答

8
您可以使用相同的算法std::unique和lambda表达式一起使用。
例如:
#include <iostream>
#include <string>
#include <functional>
#include <iterator>
#include <algorithm>

int main()
{
    std::string s = "/aaaa/***/bbbb/ccc/aa/*****/dd"; 
    char c = '*';

    s.erase( std::unique( std::begin( s ), std::end( s ), 
                          [=]( const auto &c1, const auto &c2 ) { return c1 == c && c1 == c2; } ),
             std::end( s ) ); 

    std::cout << s << '\n';             
}

程序的输出是:
/aaaa/*/bbbb/ccc/aa/*/dd

您可以删除一组重复的字符。例如:
#include <iostream>
#include <string>
#include <functional>
#include <iterator>
#include <algorithm>
#include <cstring>

int main()
{
    std::string s = "/aaaa/***/bbbb/ccc/aa/*****/dd"; 
    const char *targets = "*b";

    auto remove_chars = [=]( const auto &c1, const auto &c2 )
    {
        return strchr( targets, c1 ) && c1 == c2;
    };
    s.erase( std::unique( std::begin( s ), std::end( s ), remove_chars ), 
             std::end( s ) ); 

    std::cout << s << '\n';             
}

程序输出如下:
/aaaa/*/b/ccc/aa/*/dd

在最后一个示例中,我认为字符'\0'没有包含在字符串中。否则,您需要在lambda的逻辑表达式中再添加一个子表达式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接