繁体   English   中英

有没有比String.Replace更好的方法从字符串中删除退格?

[英]Is there a better way than String.Replace to remove backspaces from a string?

我有一个字符串从另一个源读取,如“\\ b \\ bfoo \\ bx”。 在这种情况下,它将转换为单词“fox”,因为前2个\\ b被忽略,最后的“o”被删除,然后被替换为“x”。 另外一种情况是“patt \\ b \\ b \\ b \\ b \\ b \\ b \\ b \\ b \\ b \\ bfoo”应翻译为“foo”

我用String.Replace提出了一些东西,但它很复杂,我担心它不能正常工作,它也创建了许多我想避免的新字符串对象。

有任何想法吗?

可能最简单的是迭代整个字符串。 鉴于您的输入,以下代码在1遍中完成

public string ReplaceBackspace(string hasBackspace)
{
    if( string.IsNullOrEmpty(hasBackspace) )
        return hasBackspace;

    StringBuilder result = new StringBuilder(hasBackspace.Length);
    foreach (char c in hasBackspace)
    {
        if (c == '\b')
        {
            if (result.Length > 0)
                result.Length--;
        }
        else
        {
            result.Append(c);
        }
    }
    return result.ToString();
}

我这样做的方式是低技术,但很容易理解。

创建一堆字符。 然后从头到尾遍历字符串。 如果字符是普通字符(非斜杠),则将其推入堆栈。 如果它是斜杠,并且下一个字符是'b',则弹出堆栈的顶部。 如果堆栈为空,请忽略它。

最后,依次弹出每个字符,将其添加到StringBuilder,并反转结果。

正则表达式版本:

var data = @"patt\b\b\b\b\b\b\b\b\b\bfoo";
var regex = new Regex(@"(^|[^\\b])\\b");

while (regex.IsMatch(data))
{
    data = regex.Replace(data, "");
}

优化版本(这个版本适用于退格'\\ b'而不是字符串“\\ b”):

var data = "patt\b\b\b\b\b\b\b\b\b\bfoo";
var regex = new Regex(@"[^\x08]\x08", RegexOptions.Compiled);

while (data.Contains('\b'))
{
    data = regex.Replace(data.TrimStart('\b'), "");
}
public static string ProcessBackspaces(string source)
{
    char[] buffer = new char[source.Length];
    int idx = 0;

    foreach (char c in source)
    {
        if (c != '\b')
        {
            buffer[idx] = c;
            idx++;
        }
        else if (idx > 0)
        {
            idx--;
        }
    }

    return new string(buffer, 0, idx);
}

编辑

到目前为止,我已经对答案中发布的代码做了快速粗略的基准测试(处理问题中的两个示例字符串,每个字符串100万次):

 ANSWER                 | TIME (ms)
------------------------|-----------
 Luke (this one)        |       318
 Alexander Taran        |       567
 Robert Paulson         |       683
 Markus Nigbur          |      2100
 Kamarey (new version)  |      7075
 Kamarey (old version)  |     30902

您可以向后遍历字符串,随时创建一个字符数组。 每当你点击一个退格键时,增加一个计数器,每次你点击一个普通字符时,如果你的计数器非零并且递减计数器,则跳过它。

我不确定最好的C#数据结构是什么来管理它,然后能够快速地以正确的顺序获取字符串。 StringBuilder有一个Insert方法,但我不知道是否在开始时插入字符是否有效。 您可以将字符放在堆栈中并在最后命中ToArray() - 这可能会也可能不会更快。

String myString = "patt\b\b\b\b\b\b\b\b\b\bfoo";
      List<char> chars = myString.ToCharArray().ToList();
      int delCount = 0;

      for (int i = chars.Count -1; i >= 0; i--)
      {
        if (chars[i] == '\b')
        {
          delCount++;
          chars.RemoveAt(i);
        } else {
          if (delCount > 0 && chars[i] != null) {
            chars.RemoveAt(i);
            delCount--;
          }
        }
      }

我会这样:代码没有经过测试

char[] result = new char[input.Length()];
int r =0;
for (i=0; i<input.Length(); i++){
if (input[i] == '\b'  && r>0) r--;
 else result[r]=input[i];

}

string resultsring = result.take(r);

创建一个StringBuilder并复制除退格字符之外的所有内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM