[英]Is there a better way than String.Replace to remove backspaces from a string?
I have a string read from another source such as "\\b\\bfoo\\bx". 我有一个字符串从另一个源读取,如“\\ b \\ bfoo \\ bx”。 In this case, it would translate to the word "fox" as the first 2 \\b's are ignored, and the last 'o' is erased, and then replaced with 'x'.
在这种情况下,它将转换为单词“fox”,因为前2个\\ b被忽略,最后的“o”被删除,然后被替换为“x”。 Also another case would be "patt\\b\\b\\b\\b\\b\\b\\b\\b\\b\\bfoo" should be translated to "foo"
另外一种情况是“patt \\ b \\ b \\ b \\ b \\ b \\ b \\ b \\ b \\ b \\ bfoo”应翻译为“foo”
I have come up with something using String.Replace, but it is complex and I am worried it is not working correctly, also it is creating a lot of new string objects which I would like to avoid. 我用String.Replace提出了一些东西,但它很复杂,我担心它不能正常工作,它也创建了许多我想避免的新字符串对象。
Any ideas? 有任何想法吗?
Probably the easiest is to just iterate over the entire string. 可能最简单的是迭代整个字符串。 Given your inputs, the following code does the trick in 1-pass
鉴于您的输入,以下代码在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();
}
The way I would do it is low-tech, but easy to understand. 我这样做的方式是低技术,但很容易理解。
Create a stack of characters. 创建一堆字符。 Then iterate through the string from beginning to end.
然后从头到尾遍历字符串。 If the character is a normal character (non-slash), push it onto the stack.
如果字符是普通字符(非斜杠),则将其推入堆栈。 If it is a slash, and the next character is a 'b', pop the top of the stack.
如果它是斜杠,并且下一个字符是'b',则弹出堆栈的顶部。 If the stack is empty, ignore it.
如果堆栈为空,请忽略它。
At the end, pop each character in turn, add it to a StringBuilder, and reverse the result. 最后,依次弹出每个字符,将其添加到StringBuilder,并反转结果。
Regular expressions version: 正则表达式版本:
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, "");
}
Optimized version (and this one works with backspace '\\b' and not with string "\\b"): 优化版本(这个版本适用于退格'\\ 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);
}
EDIT 编辑
I've done a quick, rough benchmark of the code posted in answers so far (processing the two example strings from the question, one million times each): 到目前为止,我已经对答案中发布的代码做了快速粗略的基准测试(处理问题中的两个示例字符串,每个字符串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
You could iterate through the string backward, making a character array as you go. 您可以向后遍历字符串,随时创建一个字符数组。 Every time you hit a backspace, increment a counter, and every time you hit a normal character, skip it if your counter is non-zero and decrement the counter.
每当你点击一个退格键时,增加一个计数器,每次你点击一个普通字符时,如果你的计数器非零并且递减计数器,则跳过它。
I'm not sure what the best C# data structure is to manage this and then be able to get the string in the right order afterward quickly. 我不确定最好的C#数据结构是什么来管理它,然后能够快速地以正确的顺序获取字符串。
StringBuilder
has an Insert
method but I don't know if it will be performant to keep inserting characters at the start or not. StringBuilder
有一个Insert
方法,但我不知道是否在开始时插入字符是否有效。 You could put the characters in a stack and hit ToArray()
at the end -- that might or might not be faster. 您可以将字符放在堆栈中并在最后命中
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--;
}
}
}
i'd go like this: code is not tested 我会这样:代码没有经过测试
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.