使用正则表达式从字符串中删除垃圾字符

6
我想从一个字符串中删除除a-z和A-Z以外的字符。为此创建了以下函数,它可以很好地工作。
public String stripGarbage(String s) {
 String good = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
 String result = "";
 for (int i = 0; i < s.length(); i++) {
     if (good.indexOf(s.charAt(i)) >= 0) {
             result += s.charAt(i);
      }
   }
 return result;
}

有没有人能告诉我更好的实现方式。可能使用正则表达式会是更好的选择。

谢谢

Harry


这个问题有点令人困惑。下面有JavaScript和C#的答案? - Jess
6个回答

5

请看以下内容:

result = result.replaceAll("[^a-zA-Z0-9]", "");

但是,如果您能理解自己的代码并且易于阅读,那么也许您已经找到了最好的解决方案:

有些人在面对问题时会想:“我知道,我会使用正则表达式。”现在他们有两个问题。


据我所知,replaceAll不是标准的JS函数,因此您还需要定义它(例如http://www.codedigest.com/CodeDigest/75-String-ReplaceAll-function-in-JavaScript.aspx)。 - Gert Grenander
+1 对于最简单的答案,但是对于“两个问题”的引用则-1——在第50次重复后它失去了一些东西。 - Alan Moore
@Alan Moore 我经常使用它的唯一原因是因为我没有勇气在身上纹上这个引语 - 这是次好的选择!!! - Robben_Ford_Fan_boy

4
以下方法比使用正则表达式和您最初的尝试更快。
public String stripGarbage(String s) {
    StringBuilder sb = new StringBuilder(s.length());
    for (int i = 0; i < s.length(); i++) {
        char ch = s.charAt(i);
        if ((ch >= 'A' && ch <= 'Z') || 
            (ch >= 'a' && ch <= 'z') ||
            (ch >= '0' && ch <= '9')) {
            sb.append(ch);
        }
    }
    return sb.toString();
}

要点:

  • 在循环中使用StringBuilder比字符串连接快得多。(后者会生成N-1个垃圾字符串,并复制N *(N + 1)/ 2个字符以构建包含N个字符的字符串。)

  • 如果您对结果字符串的长度有一个很好的估计,最好预先分配StringBuilder来容纳那些字符数。(但是,如果您没有很好的估计,内部重新分配等成本会摊销为O(N),其中N是最终字符串长度…因此这通常不是主要问题。)

  • 与(最多)3个字符范围进行比较测试的字符搜索平均速度比在62个字符的字符串中搜索字符快得多。

  • switch语句可能更快,特别是如果有更多的字符范围。 但是,在这种情况下,需要列出所有字母和数字的情况,需要更多的代码行。

  • 如果非垃圾字符与Character类的现有谓词匹配(例如Character.isLetter(char)等),则可以使用它们。 如果您想匹配任何字母或数字…而不仅仅是ASCII字母和数字,则这将是一个很好的选择。

  • 其他要考虑的选择是使用预先填充非垃圾字符的HashSet<Character>或按字符索引的boolean[]。 如果非垃圾字符集在编译时未知,则这些方法效果很好。


1

这个正则表达式是有效的:

result=s.replace(/[^A-Z0-9a-z]/ig,'');

s是传递给您函数的字符串,result是仅包含字母数字的字符串。


1

我知道这篇文章有点旧了,但你可以通过使用System.Char结构来简化Stephen C的答案。

public String RemoveNonAlphaNumeric(String value)
{
    StringBuilder sb = new StringBuilder(value);
    for (int i = 0; i < value.Length; i++)
    {
        char ch = value[i];

        if (Char.IsLetterOrDigit(ch))
        {
            sb.Append(ch);
        }
    }
    return sb.ToString();
}

仍然以更紧凑的方式完成相同的事情。

Char具有一些非常出色的检查文本的功能。以下是一些供您将来参考的功能。

Char.GetNumericValue()         
Char.IsControl()              
Char.IsDigit()             
Char.IsLetter()              
Char.IsLower()             
Char.IsNumber()         
Char.IsPunctuation()          
Char.IsSeparator()            
Char.IsSymbol()         
Char.IsWhiteSpace()

你似乎已经从Java转向了C#。 - Alan Moore
我看到了这个问题,然后从我的代码库中找到了一小段代码。C#和Java在语法上非常相似,以至于我没有注意到最初的问题是关于Java的。但是,如果有人正在使用C#,那么这段代码是有用的。 - Kila Morton
Java确实有Character.isLetterOrDigit()和其他一些Character.isXXX()的方法。 - Samuel

0
/**
 *   Remove characters from a string other than ASCII
 *   
 * */
 private static StringBuffer goodBuffer = new StringBuffer();
    // Static initializer for ACSII
static {
     for (int c=1; c<128; c++) {
         goodBuffer.append((char)c);
       }
}

public String stripGarbage(String s) {
     //String good = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";       
     String good = goodBuffer.toString();
     String result = "";
     for (int i = 0; i < s.length(); i++) {
         if (good.indexOf(s.charAt(i)) >= 0) {
                 result += s.charAt(i);
          }
         else
             result += " ";
       }
     return result;
    }

不要只贴一段代码,还请解释为什么这段代码可以解决所提出的问题。没有解释,这不是一个答案。 - Martijn Pieters

0

这个有效:

public static String removeGarbage(String s) {
        String r = "";
        for ( int i = 0; i < s.length(); i++ )
            if ( s.substring(i,i+1).matches("[A-Za-z]") ) // [A-Za-z0-9] if you want include numbers
                r = r.concat(s.substring(i, i+1));
        return r;
    }

(编辑:虽然它不是很高效)

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