【问题标题】:Replace the string of special characters in C#替换C#中的特殊字符字符串
【发布时间】:2017-11-26 16:17:30
【问题描述】:

我的要求是:

我必须用string.Empty替换一些特殊字符,如* ' " , _ & # ^ @,我必须用-替换空格。

这是我的代码:

 Charseparated = Charseparated
    .Replace("*","")
    .Replace("'","")
    .Replace("&","")
    .Replace("@","") ...

要替换这么多字符,我必须使用尽可能多的 Replace,这是我想避免的。

是否有另一种有效的方法来删除特殊字符,但同时用-替换空格?

【问题讨论】:

  • 使用正则表达式
  • 只是想补充一点,如果这是关于生成有效的文件名,您可以使用Sytem.IO.Path.GetInvalidFileNameChars 获取无效字符集。
  • 特别如何?这些不是特殊字符。您是否正在尝试清理文件路径?阅读带有引用文本的 CSV?清理 SQL 输入?每种情况都有更好的替代品,不需要更换
  • StringBuilder.Replace()String.Replace() 的更有效替代方案,如here 所述。不过,您仍然需要多次调用Replace()
  • 你有问题。你用正则表达式解决它。现在你有两个问题。 (对不起,我忍不住:)

标签: c# replace


【解决方案1】:

进行一系列更改并对其进行迭代:

var replacements = new []
                   { new { Old = "*", New = string.Empty }
                   // all your other replacements, removed for brevity
                   , new { Old = " ", New = "-" }
                   }

foreach (var r in replacements)
{
    Charseparated = Charseparated.Replace(r.Old, r.New);
}

【讨论】:

  • 它基本上与 OP 发布的内容相同,但输入更少
  • 不,它与 OP 完全相同,但重复性较低。这就是整个目标吧?
  • 这会产生很多临时字符串。如果输入数据很多,并且在垃圾收集中占用大量 CPU,则会造成巨大的内存浪费
  • @PanagiotisKanavos charseperated 上面没有声明它可能是 StringBuilder,如果不是,它很可能应该。
  • 除非我们得到一个特定的用例,否则每个“性能测量”都是没有意义的。如果可能的输入大小是例如,对 100k 字符串执行测量是不相关的平均低于 20 个字符。在这种情况下,“避免过早优化”意味着:使代码工作和可维护,并且仅在您的测量结果表明其他情况时才进行优化。
【解决方案2】:

我相信,最好在这里使用正则表达式,如下所示

s/[*'",_&#^@]/ /g

您可以为此目的使用Regex

Regex reg = new Regex("[*'\",_&#^@]");
str1 = reg.Replace(str1, string.Empty);

Regex reg1 = new Regex("[ ]");
str1 = reg.Replace(str1, "-");

【讨论】:

  • 您的正则表达式如何区分在一种情况下替换为 string.empty 而在另一种情况下替换为-?对我来说,您似乎总是用一个空格来替换,而这从来都不是必需的。 (还是我错了?)
  • @PatrickHofman。好吧,请参阅答案中的编辑,但这样一来,您的答案并没有描述所有可能的字符......对吗?
  • 同意,但从概念上讲它有效。你的没有或不清楚。
  • @Venkat 已更正。
  • 还要考虑静态 Regex.Replace(input, pattern, replacement)。我更喜欢一次性使用正则表达式
【解决方案3】:

string.Split 与分隔符数组一起使用,并将它们聚合回1 个字符串中。不过,用string.Empty 和用“-”替换“”必须分别进行。

        var res = "23#$36^45&".Split(new[] {'#', '$', '^', '&'}, StringSplitOptions.RemoveEmptyEntries)
            .Aggregate((s, s1) => s + s1);
        // "233645"

【讨论】:

  • .Aggregate在这里太不自然了,为什么不string.Concat("23#$36^45&".Split(...));
  • 是真的...string.Concat 更适合这个用例,当你只想让那些字符消失时。但是我之前使用过这种模式的场景,也需要替换,聚合实际上类似于(s, s1) => s+ "_" + s1
【解决方案4】:

使用正则表达式

Regex.Replace("Hello*Hello'Hello&Hello@Hello Hello", @"[^0-9A-Za-z ,]", "").Replace(" ", "-")

它将所有特殊字符替换为string.Empty,空格替换为“-”

【讨论】:

  • 这不是错字 - 有空格。因为我们想用“-”替换空格
  • 首先它用空字符串替换所有特殊字符。第一次使用 regx 替换,空格会在那里,然后用连字符替换空格
  • 对不起,我显然有一个特殊的时刻。您完全正确,我将删除我的 cmets(在给您足够的时间让您阅读此内容之后)。我现在显然不应该看 SO。 ;-)
【解决方案5】:

string.Replace 太可怕了,太可怕了,太可怕了,专业程序员不应该在任何地方使用,除了最琐碎的任务。

字符串是不可变的。这意味着每次执行 string.replace(或 myString = myString + "lalala" 等)时,系统都需要完成所有后勤工作(创建新指针、复制内容、垃圾收集等)。顺便说一句,Patrick 上面的回答就是这样做的(但代码可读性更好)。

如果只需要执行几次,这不是问题 -- 代码可以立即阅读。

但是一旦你把这个操作放在一个循环中,你就需要用另一种方式来编写它。我自己会去使用正则表达式:

string inStr = "lala * lalala @ whowrotethis # ohcomeon &";
string outStr = Regex.Replace(inStr , "[*|@|*|&]", string.Empty);

【讨论】:

  • string.Replace 太可怕了,太可怕了,太可怕了,专业程序员不应该在任何地方使用,除了最琐碎的任务。。这太可怕了。 string.Replace一定要小心使用,不使用解决不了问题。
  • 同意(我确实提到在操作中使用它几次是好的)但仍然:如果在循环中使用,它必须改变。我在多次进行代码审查时已经提出了这一点。 IMO 了解他们的代码在幕后的作用非常重要,尤其是对于初级同事而言。
  • @PatrickHofman 由重复 Replace 调用生成的多个临时字符串非常可怕。在日志文件上尝试一下,观察内存使用量飙升至千兆字节。一个正则表达式可以将相同的工作速度提高 10 倍,而只需 20MB 仅仅是因为它不会生成无用的临时字符串
  • String.Replace 不是“可怕的、可怕的、可怕的”,你是否应该使用它与你是否以编程为职业无关,而与你想要实现的目标有关.此外,您的正则表达式中有多余的 | 字符。
  • @MattiVirkkunen .NET Core 团队花费了大量时间和精力来消除虚假分配,甚至引入了一个新的 UTF8String 类。不管你怎么看,多个替换都是个坏主意。更多的是关于规模 - 5 次替换并没有那么多。 5*1000 行太多了。如果只需要过滤掉字符,则对字符进行一次扫描和过滤会更好
【解决方案6】:

这是最优化和最简单的方法

    public void foo()
    {
        string input = "A sample input a*b#c@d";
        string unwanted = "*'\",_&#^@";
        List<char> unwantedChars = unwanted.ToList<char>();
        StringBuilder sb = new StringBuilder();

        input = input.Replace(' ', '-');
        foreach(char c in input)
        {
            if (!unwantedChars.Any(x => x == c))
                sb.Append(c);
        }
        string output = sb.ToString(); //A-sample-input-abcd
    }

【讨论】:

  • 不需要转换为List&lt;char&gt;StringContains 方法,您可以直接在循环中使用它:if (!unwanted.Contains(c))
  • 最佳?不。充其量它会像正则表达式一样快
【解决方案7】:

你可以像这样使用正则表达式。

string Charseparated = "test * -";

var replacements = new Dictionary<string, string>()
{
   {"*", string.Empty},
   {" ", "-"}
};

var reg = new Regex(String.Join("|", replacements.Keys.Select(k => Regex.Escape(k))));
var reg_replace = reg.Replace(Charseparated, m => replacements[m.Value]);

【讨论】:

    【解决方案8】:

    LINQ 和 char[] 方式:

       string f = Filter("*WHAT/ #PO#PO");
    

    它返回 WHAT-POPO:

        private string Filter(string s)
        {
            var chars = new[] { '*', '/', '#' };
            var filteredChars = s.ToArray();
            return new string(filteredChars
                     .Where(ch => !chars.Contains(ch) )
                     .Select(ch => ch == ' ' ? '-' : ch).ToArray());
        }
    

    【讨论】:

      【解决方案9】:

      你可以试试LINQ

        var source = "lala * lalala @ whowrotethis # ohcomeon &";
      
        var result = string.Concat(source.Select(c => c == ' ' 
           ? "-" 
           : "*'\",_&#^@".Contains(c) ? "" 
           : c.ToString()));
      

      【讨论】:

      • c.ToString() 最终为每个输入字符创建一个临时字符串。最好只用字符处理并在最后将结果转换为字符串
      • Where(c=&gt;"*'\",_&amp;#^@".Contains(c)).Select(c =&gt; c == ' ' ? '-':c) 也会导致对输入字符串进行扫描 - where 消除不需要的字符,Select 执行替换
      • @PanagiotisKanavos:您的Where 条件需要在它前面加上!(目前它返回所有特殊字符而不是其他所有字符)。
      【解决方案10】:

      OP 要求一种“有效”的方式来替换字符串。

      就性能而言,使用 Regex 并不是最好的解决方案(如果考虑到可读性或方便性,它可能...)。

      相反,StringBuilder 的性能要好得多,如果您处理大数据,这可能会变得很重要。

       StringBuilder sb = new StringBuilder(myString);
       foreach (string unwanted in collectionOfUnwantedStrings)
               {
                   sb.Replace(unwanted, string.Empty);
               }
      

      【讨论】:

        【解决方案11】:

        在一次采访中向我提出了同样的问题...给了我一个包含特殊字符的字符串,并被要求从输入字符串中删除特殊字符并将其反转。

        下面是简单高效的程序:

        public class Program
            {
                static void Main(string[] args)
                {
                    string name = "T@T@P&!M#";
        
                    Program obj = new Program();
        
                    Console.WriteLine(obj.removeSpecialCharacters(name));
        
                    Console.WriteLine(obj.reverseString(obj.removeSpecialCharacters(name)));
        
                    Console.ReadLine();
        
        
                }
        
                private string removeSpecialCharacters(string input)
                {
                    string[] specialCharacters = new string[] { "@", "&", "!", "#" };
        
                    for (int i = 0; i < specialCharacters.Length; i++)
                    {
                        if (input.Contains(specialCharacters[i]))
                        {
                            input = input.Replace(specialCharacters[i], "");
                        }
                    }
        
                    return input;
                }
        
                private string reverseString(string input)
                {
                    string reverseString = "";
        
                    for (int i = input.Length - 1; i >= 0; i--)
                    {
                        reverseString = reverseString + input[i];
                    }
        
                    return reverseString;
                }
            }
        

        【讨论】:

        【解决方案12】:

        传递带有特殊字符的字符串。你只有没有特殊字符的字符串。注意 - 在“可替换”列表中添加您的特殊字符。

        protected string hasSpecialChar(string input)
                {
                    string[] replaceables = new[] { @"\", "|", "!", "#", "$", "%", "&", "/", "=", "?", "»", "«", "@", "£", "§", "€", "{", "}", "^", ";", "'", "<", ">", ",", "`" };
                    string rxString = string.Join("|", replaceables.Select(s => Regex.Escape(s)));
                    return Regex.Replace(input, rxString, "-");
                }
        

        【讨论】:

        • 该问题还指定应将空格替换为-,因此您需要对答案稍作修改
        【解决方案13】:
        Regex.Replace(source_string, @"[^\w\d]", "_");
        

        这会将给定字符串 (source_string) 中的所有非字母和非数字替换为“_”。

        【讨论】:

          猜你喜欢
          • 2012-01-07
          • 1970-01-01
          • 2014-12-07
          • 1970-01-01
          相关资源
          最近更新 更多