【问题标题】:How do you remove repeated characters in a string如何删除字符串中的重复字符
【发布时间】:2010-12-13 14:49:13
【问题描述】:

我有一个允许用户评论照片的网站。 当然,用户会留下这样的 cmets:

'OMGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG !!!!!!!!!!!!!!!'

'你成功了'

你懂的。

基本上,我想通过删除至少大部分多余的重复字符来缩短这些 cmets。 我确定有一种方法可以使用正则表达式来做到这一点。我只是想不通。

有什么想法吗?

【问题讨论】:

  • 我认为这不是一个好的解决方案......这会将评论的语言学改变为作者不打算的东西。基本上他们的意图是愚蠢的,你会把它变成胡言乱语。例如,当有人说“booooo!”时你会把它变成“bo!”吗?数字呢?用户名?网址?
  • 你最好从三个重复的字母开始缩短 - 双倍的字母在英语中都是常见的。
  • 输入良好的愚蠢垃圾邮件仍然是愚蠢的垃圾邮件,只是稍微难以一目了然。
  • 另请参阅此处,了解为什么这类事情可能不是一个好主意的一个笨拙示例:codinghorror.com/blog/2008/10/…
  • 您将允许多少个重复字符(即“you suucckk”与“you sssuuucccckkk”与“you ssssuuuucccckkkk”)?或者像“LOLOLOLOLOLOLOLOLOL”或“s s s s u u u u c c c c c k k k k”这样的重复字符簇怎么样?

标签: c# regex string


【解决方案1】:

请记住,英语经常使用双字母,您可能不想盲目地消除它们。这是一个正则表达式,它将摆脱双精度之外的任何内容。

Regex r = new Regex("(.)(?<=\\1\\1\\1)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);

var x = r.Replace("YOU SUCCCCCCCCCCCCCCCCCKKKKKKKKKKKKKKKKKK", String.Empty);
// x = "YOU SUCCKK"

var y = r.Replace("OMGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG!!!!!!!!!!!!!!!", String.Empty);
// y = "OMGG!!"

【讨论】:

  • 俄语有时使用三个字母(很少变化),仅供参考。
  • 有趣,我不知道。增加正则表达式以了解一组预期会加倍或加倍并表现得适当的字母会很酷。
  • 它没有回答这个问题,你的版本留下了双打。
  • @metabuddy 仔细阅读问题。要求是删除大部分重复项。鉴于提供的答案,您应该能够进行必要的调整以删除所有重复项。
【解决方案2】:

您是否特别想缩短代码中的字符串,或者仅仅使验证失败并再次向用户显示表单并显示验证错误就足够了吗?诸如“重复字符过多”之类的内容。

如果后者可以接受,@"(\w)\1{2}" 应匹配 3 个或更多字符(解释为“重复”两次或更多次)。

编辑:正如@Piskvor 指出的那样,这将匹配恰好 3 个字符。它适用于匹配,但不适用于替换。他的版本@"(\w)\1{2,}" 更适合替换。但是,我想指出,我认为替换不是这里的最佳做法。最好让表单验证失败,而不是尝试清理提交的文本,因为可能会出现边缘情况,您可能会将原本可读(即使不合理)的文本变成废话。

【讨论】:

  • (\w)\1{2,},我会说。 (\w)\1{2} 将完全匹配三个字符。
  • @Piskvor:你确定吗?无论如何,我都不是正则表达式专家,但我只是在“abbbbbbbcdef”上测试了我的,它匹配。 (至少在 .NET 中,它甚至可能表现出非标准行为,但却是有问题的环境。)
  • 哦,它会 match 好吧(因为有 are 个子字符串正好重复三个),它只是不会匹配整个重复- 注意它只匹配粗体部分: "a bbb bbbbcdef" 。进行匹配和替换并不完全方便。
  • @Piskvor:啊,我现在明白你的意思了。虽然我绝对认为自动更换不是去这里的方式。 (您上面的评论很好地说明了它的一个危险。)将表单作为无效提交踢回用户可能是更好的做法。
  • @Piskvor:同意。这是对潜在滥用的快速简便的检查(要执行的许多操作之一),但这绝不是一个完整的解决方案。在这一点上,这是一个投资回报率的问题,真的。如果没有一个稳固的自我维护社区,则由网站管理员决定在检测不良输入方面投入多少工作,并尝试从他们的开发中获得最大收益。
【解决方案3】:
var nonRepeatedChars = myString.ToCharArray().Distinct().Where(c => !char.IsWhiteSpace(c) || !myString.Contains(c)).ToString();

【讨论】:

    【解决方案4】:

    正则表达式将是矫枉过正。 试试这个:

    public static string RemoveRepeatedChars(String input, int maxRepeat)
        {
            if(input.Length==0)return input;
    
            StringBuilder b = new StringBuilder;
            Char[] chars = input.ToCharArray();
            Char lastChar = chars[0];
            int repeat = 0;
            for(int i=1;i<input.Length;i++){
                if(chars[i]==lastChar && ++repeat<maxRepeat)
                {
                    b.Append(chars[i]);
                }
                else
                {
                    b.Append(chars[i]);
                    repeat=0;
                    lastChar = chars[i];
                }
            }
            return b.ToString();
        }
    

    【讨论】:

      【解决方案5】:

      Distinct() 将删除所有重复项,但显然不会将“A”和“a”视为相同。

      Console.WriteLine(new string("Asdfasdf".Distinct().ToArray()));
      

      输出“Asdfa”

      【讨论】:

        【解决方案6】:
        var test = "OMMMMMGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGMMM";
        
        test.Distinct().Select(c => c.ToString()).ToList()
                .ForEach(c =>
                    { 
                        while (test.Contains(c + c)) 
                        test = test.Replace(c + c, c); 
                    }
                );
        

        【讨论】:

          【解决方案7】:

          编辑:糟糕的建议,请不要阅读,我真的配得上我的 -1 :)

          我在 technical nuggets 上找到了你正在寻找的东西。

          除了一个很长的正则表达式之外别无他法,因为我从未听说过用于重复的正则表达式符号......

          这是一个完整的例子,我不会在这里粘贴它,但我认为这将完全回答你的问题。

          【讨论】:

          • 啊,太可怕了。 Ääääääɫɫɫɫśśśśöööööööö,这只会停止列入黑名单的字符 - 由于 Unicode 得到广泛支持,因此并不完全有用。阅读有关正则表达式反向引用的信息 - 它们存在,即使您之前从未听说过它们。
          • @Piskvor :是的,我正在寻找它们,但我找不到解释的地方。事实上,在@"(\w)\1{2}" 中,我不明白 \1 代表什么。如果你有一个解释它的链接,那对我来说非常有用:)
          • @LaGrandMere:我手边没有链接,但\1 基本上意味着它正在回顾正则表达式中的第一组(第一组括号),即(\w)。跨度>
          • @David 非常感谢您的解释 :) 如果有人有链接,我将不胜感激!
          • 呃 ...在“不应命名的搜索引擎”中输入 regex backreferences 给了我“大约 40,900 个结果”——第一个命中非常清楚地解释了 IMO(以及指向确切类型问题的链接OP 发布:regular-expressions.info/duplicatelines.html)。缩短:(\w) 是第一个捕获组(匹配可以在模式的后面进一步引用),\1 是对这个匹配的引用,{2} 匹配之前的 \1 正好 2 次(应该是 {2,}匹配 2 次或更多次)。
          猜你喜欢
          • 1970-01-01
          • 2015-06-07
          • 1970-01-01
          • 2013-11-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-30
          • 1970-01-01
          相关资源
          最近更新 更多