Ответ 1
int index = sourceString.IndexOf(removeString);
string cleanPath = (index < 0)
? sourceString
: sourceString.Remove(index, removeString.Length);
Мне нужно удалить первое (и ТОЛЬКО первое) возникновение строки из другой строки.
Ниже приведен пример замены строки "\\Iteration"
. Это:
ProjectName\\Iteration\\Release1\\Iteration1
станет следующим:
ProjectName\\Release1\\Iteration1
Вот код, который делает это:
const string removeString = "\\Iteration";
int index = sourceString.IndexOf(removeString);
int length = removeString.Length;
String startOfString = sourceString.Substring(0, index);
String endOfString = sourceString.Substring(index + length);
String cleanPath = startOfString + endOfString;
Это похоже на много кода.
Итак, мой вопрос таков: есть ли более чистый/более читаемый/более сжатый способ сделать это?
int index = sourceString.IndexOf(removeString);
string cleanPath = (index < 0)
? sourceString
: sourceString.Remove(index, removeString.Length);
string myString = sourceString.Remove(sourceString.IndexOf(removeString),removeString.Length);
EDIT: @OregonGhost прав. Я сам сломал script с помощью условных выражений, чтобы проверить такое возникновение, но я работал в предположении, что строки были присвоены друг другу некоторым требованием. Возможно, что правила обработки исключений для бизнеса, как ожидается, поймут эту возможность. Я сам воспользуюсь несколькими дополнительными строками для выполнения условных проверок, а также для того, чтобы сделать его более читаемым для младших разработчиков, которым не хватает времени, чтобы прочитать его достаточно тщательно.
sourceString.Replace(removeString, "");
Написал быстрый TDD-тест для этого
[TestMethod]
public void Test()
{
var input = @"ProjectName\Iteration\Release1\Iteration1";
var pattern = @"\\Iteration";
var rgx = new Regex(pattern);
var result = rgx.Replace(input, "", 1);
Assert.IsTrue(result.Equals(@"ProjectName\Release1\Iteration1"));
}
rgx.Replace(input, ", 1); говорит, чтобы посмотреть в поле ввода для чего-либо, соответствующего шаблону, с" 1". 1 раз.
Вы можете использовать метод расширения для удовольствия. Обычно я не рекомендую прикреплять методы расширения к такому классу общего назначения, как строка, но, как я уже сказал, это весело. Я позаимствовал @Luke ответ, потому что нет смысла повторно изобретать колесо.
[Test]
public void Should_remove_first_occurrance_of_string() {
var source = "ProjectName\\Iteration\\Release1\\Iteration1";
Assert.That(
source.RemoveFirst("\\Iteration"),
Is.EqualTo("ProjectName\\Release1\\Iteration1"));
}
public static class StringExtensions {
public static string RemoveFirst(this string source, string remove) {
int index = source.IndexOf(remove);
return (index < 0)
? source
: source.Remove(index, remove.Length);
}
}
Я определенно согласен, что это идеально подходит для метода расширения, но я думаю, что его можно немного улучшить.
public static string Remove(this string source, string remove, int firstN)
{
if(firstN <= 0 || string.IsNullOrEmpty(source) || string.IsNullOrEmpty(remove))
{
return source;
}
int index = source.IndexOf(remove);
return index < 0 ? source : source.Remove(index, remove.Length).Remove(remove, --firstN);
}
Это немного рекурсия, которая всегда интересна.
Вот простой unit test:
[TestMethod()]
public void RemoveTwiceTest()
{
string source = "look up look up look it up";
string remove = "look";
int firstN = 2;
string expected = " up up look it up";
string actual;
actual = source.Remove(remove, firstN);
Assert.AreEqual(expected, actual);
}