从C#字符串中删除字符

193

我该如何从字符串中删除字符?比如:"My name @is ,Wan.;'; Wan"

我想要从该字符串中删除字符'@',',','.',';','\'',使其变为"My name is Wan Wan"


这个问题的真正正确解决方法在微软文档中已经简单地解释了:https://learn.microsoft.com/en-us/dotnet/standard/base-types/how-to-strip-invalid-characters-from-a-string。再也没有比这更容易的了。 - Fattie
22个回答

6
new List<string> { "@", ",", ".", ";", "'" }.ForEach(m => str = str.Replace(m, ""));

4

我来翻译一下。

制作一个扩展程序,用于从字符串中删除字符:

public static string RemoveChars(this string input, params char[] chars)
{
    var sb = new StringBuilder();
    for (int i = 0; i < input.Length; i++)
    {
        if (!chars.Contains(input[i]))
            sb.Append(input[i]);
    }
    return sb.ToString();
}

它可以这样使用:

string str = "My name @is ,Wan.;'; Wan";
string cleanedUpString = str.RemoveChars('@', ',', '.', ';', '\'');

或者就像这样:
string str = "My name @is ,Wan.;'; Wan".RemoveChars('@', ',', '.', ';', '\'');

2
这是最佳解决方案,因为它使得内存分配的数量最少。我还会将原始字符串的长度设置为字符串构建器的初始容量,例如:new StringBuilder(input.Length),以此来减少内存分配的数量。 - treaschf

4

似乎最简单的方法是将LINQ和string.Concat组合使用:

var input = @"My name @is ,Wan.;'; Wan";
var chrs = new[] {'@', ',', '.', ';', '\''};
var result = string.Concat(input.Where(c => !chrs.Contains(c)));
// => result = "My name is Wan Wan" 

请查看C#演示。请注意,string.Concat string.Join(“”,...)的快捷方式。

请注意,使用正则表达式删除单个已知字符仍然可以动态构建,尽管认为正则表达式速度较慢。 但是,这里有一种构建此类动态正则表达式的方法(其中您只需要一个字符类):

var pattern = $"[{Regex.Escape(new string(chrs))}]+";
var result = Regex.Replace(input, pattern, string.Empty);

请参见另一个 C# 演示。 正则表达式将如下所示:[@,\.;']+(匹配一个或多个连续出现的 @,.;' 字符),其中点号不必转义,但是 Regex.Escape 将需要用于转义其他必须转义的字符,例如 \ ,^]-,其在字符类内的位置无法预测。

1
LINQ方式在某些情况下速度非常慢。 - drzaus

4

字符串只是一个字符数组,因此可以使用Linq进行替换(与上面的Albin类似,但使用Linq包含语句进行替换):

var resultString = new string(
        (from ch in "My name @is ,Wan.;'; Wan"
         where ! @"@,.;\'".Contains(ch)
         select ch).ToArray());

第一个字符串是要替换字符的字符串,第二个字符串是包含字符的简单字符串。

Albin的Linq解决方案可能更好,除非您希望过滤掉其他字符(不包括空格、字母和数字)。 - alistair

4

这里有一种很好的方法可以从文件名中删除无效字符:

string.Join(string.Empty, filename.Split(System.IO.Path.GetInvalidFileNameChars()));

2

这里有很多好的答案,我来补充一下,还提供了几个单元测试以帮助测试正确性。我的解决方案与@Rianne的相似,但使用ISet提供替换字符的O(1)查找时间(也类似于@Albin Sunnanbo的Linq解决方案)。

    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// Returns a string with the specified characters removed.
    /// </summary>
    /// <param name="source">The string to filter.</param>
    /// <param name="removeCharacters">The characters to remove.</param>
    /// <returns>A new <see cref="System.String"/> with the specified characters removed.</returns>
    public static string Remove(this string source, IEnumerable<char> removeCharacters)
    {
        if (source == null)
        {
            throw new  ArgumentNullException("source");
        }

        if (removeCharacters == null)
        {
            throw new ArgumentNullException("removeCharacters");
        }

        // First see if we were given a collection that supports ISet
        ISet<char> replaceChars = removeCharacters as ISet<char>;

        if (replaceChars == null)
        {
            replaceChars = new HashSet<char>(removeCharacters);
        }

        IEnumerable<char> filtered = source.Where(currentChar => !replaceChars.Contains(currentChar));

        return new string(filtered.ToArray());
    }

NUnit(2.6+)的测试在这里

using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;

[TestFixture]
public class StringExtensionMethodsTests
{
    [TestCaseSource(typeof(StringExtensionMethodsTests_Remove_Tests))]
    public void Remove(string targetString, IEnumerable<char> removeCharacters, string expected)
    {
        string actual = StringExtensionMethods.Remove(targetString, removeCharacters);

        Assert.That(actual, Is.EqualTo(expected));
    }

    [TestCaseSource(typeof(StringExtensionMethodsTests_Remove_ParameterValidation_Tests))]
    public void Remove_ParameterValidation(string targetString, IEnumerable<char> removeCharacters)
    {
        Assert.Throws<ArgumentNullException>(() => StringExtensionMethods.Remove(targetString, removeCharacters));
    }
}

internal class StringExtensionMethodsTests_Remove_Tests : IEnumerable
{
    public IEnumerator GetEnumerator()
    {
        yield return new TestCaseData("My name @is ,Wan.;'; Wan", new char[] { '@', ',', '.', ';', '\'' }, "My name is Wan Wan").SetName("StringUsingCharArray");
        yield return new TestCaseData("My name @is ,Wan.;'; Wan", new HashSet<char> { '@', ',', '.', ';', '\'' }, "My name is Wan Wan").SetName("StringUsingISetCollection");
        yield return new TestCaseData(string.Empty, new char[1], string.Empty).SetName("EmptyStringNoReplacementCharactersYieldsEmptyString");
        yield return new TestCaseData(string.Empty, new char[] { 'A', 'B', 'C' }, string.Empty).SetName("EmptyStringReplacementCharsYieldsEmptyString");
        yield return new TestCaseData("No replacement characters", new char[1], "No replacement characters").SetName("StringNoReplacementCharactersYieldsString");
        yield return new TestCaseData("No characters will be replaced", new char[] { 'Z' }, "No characters will be replaced").SetName("StringNonExistantReplacementCharactersYieldsString");
        yield return new TestCaseData("AaBbCc", new char[] { 'a', 'C' }, "ABbc").SetName("CaseSensitivityReplacements");
        yield return new TestCaseData("ABC", new char[] { 'A', 'B', 'C' }, string.Empty).SetName("AllCharactersRemoved");
        yield return new TestCaseData("AABBBBBBCC", new char[] { 'A', 'B', 'C' }, string.Empty).SetName("AllCharactersRemovedMultiple");
        yield return new TestCaseData("Test That They Didn't Attempt To Use .Except() which returns distinct characters", new char[] { '(', ')' }, "Test That They Didn't Attempt To Use .Except which returns distinct characters").SetName("ValidateTheStringIsNotJustDistinctCharacters");
    }
}

internal class StringExtensionMethodsTests_Remove_ParameterValidation_Tests : IEnumerable
{
    public IEnumerator GetEnumerator()
    {
        yield return new TestCaseData(null, null);
        yield return new TestCaseData("valid string", null);
        yield return new TestCaseData(null, new char[1]);
    }
}

2

这是我通常在相同情况下使用的一种强大的方法:

private string Normalize(string text)
{
        return string.Join("",
            from ch in text
            where char.IsLetterOrDigit(ch) || char.IsWhiteSpace(ch)
            select ch);
}

Enjoy...


1

我将其制作为扩展方法,并使用字符串数组,我认为string[]char[]更有用,因为字符也可以是字符串:

public static class Helper
{
    public static string RemoverStrs(this string str, string[] removeStrs)
    {
        foreach (var removeStr in removeStrs)
            str = str.Replace(removeStr, "");
        return str;
    }
}

然后您可以在任何地方使用它:
string myname = "My name @is ,Wan.;'; Wan";
string result = myname.RemoveStrs(new[]{ "@", ",", ".", ";", "\\"});

1
new[] { ',', '.', ';', '\'', '@' }
.Aggregate("My name @is ,Wan.;'; Wan", (s, c) => s.Replace(c.ToString(), string.Empty)); 

1

老派的就地复制/覆盖:

  private static string RemoveDirtyCharsFromString(string in_string)
     {
        int index = 0;
        int removed = 0;

        byte[] in_array = Encoding.UTF8.GetBytes(in_string);

        foreach (byte element in in_array)
        {
           if ((element == ' ') ||
               (element == '-') ||
               (element == ':'))
           {
              removed++;
           }
           else
           {
              in_array[index] = element;
              index++;
           }
        }

        Array.Resize<byte>(ref in_array, (in_array.Length - removed));
        return(System.Text.Encoding.UTF8.GetString(in_array, 0, in_array.Length));
     }

对于其他方法的效率(即在C#执行期间发生的所有函数调用和实例化的开销),我不确定。


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