Возьмите привет и привет в качестве примера.
При этом hello и hlo уменьшаются до ello и lo
С этим по правилу 3 результат совпадает.
Probably the easiest is to just iterate over the entire string. Given your inputs, the following code does the trick in 1-pass
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, "");
}
Оптимизированная версия (и эта работает с backspace '\ 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);
}
РЕДАКТИРОВАТЬ
Я сделал быстрый грубый тест кода, размещенного в ответы до сих пор (обработка двух примеров строк из вопроса, миллион раз каждая):
ANSWER | TIME (ms)
------------------------|-----------
Luke (this one) | 318
Alexander Taran | 567
Robert Paulson | 683
Markus Nigbur | 2100
Kamarey (new version) | 7075
Kamarey (old version) | 30902
я бы пошел так: код не проверен
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 и скопируйте все, кроме символов возврата на одну позицию.
Вы можете перебирать строку назад, создавая массив символов по мере продвижения. Каждый раз, когда вы нажимаете клавишу Backspace, увеличиваете счетчик, и каждый раз, когда вы нажимаете нормальный символ, пропускайте его, если ваш счетчик ненулевой, и уменьшайте счетчик.
Я не уверен, что лучшая структура данных 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--;
}
}
}