Есть ли в .Net замена строки без учета регистра без использования Regex? - PullRequest
19 голосов
/ 05 апреля 2011

Недавно мне пришлось выполнить некоторые замены строк в .net, и я обнаружил, что для этой цели я разрабатываю функцию замены регулярных выражений. После того, как он заработал, я не мог не думать, что в .Net должна быть встроенная операция замены без учета регистра, которая мне не хватает?

Конечно, когда есть так много других строковых операций, которые поддерживают сравнение без учета регистра, например;

var compareStrings  = String.Compare("a", "b", blIgnoreCase);
var equalStrings    = String.Equals("a", "b", StringComparison.CurrentCultureIgnoreCase);

тогда должен быть встроенный эквивалент для замены?

Ответы [ 8 ]

23 голосов
/ 05 апреля 2011

Нашел один в комментариях здесь: http://www.codeproject.com/Messages/1835929/this-one-is-even-faster-and-more-flexible-modified.aspx

static public string Replace(string original, string pattern, string replacement, StringComparison comparisonType)
{
     return Replace(original, pattern, replacement, comparisonType, -1);
}

static public string Replace(string original, string pattern, string replacement, StringComparison comparisonType, int stringBuilderInitialSize)
{
     if (original == null)
     {
         return null;
     }

     if (String.IsNullOrEmpty(pattern))
     {
         return original;
     }


     int posCurrent = 0;
     int lenPattern = pattern.Length;
     int idxNext = original.IndexOf(pattern, comparisonType);
     StringBuilder result = new StringBuilder(stringBuilderInitialSize < 0 ? Math.Min(4096, original.Length) : stringBuilderInitialSize);

     while (idxNext >= 0)
     {
        result.Append(original, posCurrent, idxNext - posCurrent);
        result.Append(replacement);

        posCurrent = idxNext + lenPattern;

        idxNext = original.IndexOf(pattern, posCurrent, comparisonType);
      }

      result.Append(original, posCurrent, original.Length - posCurrent);

      return result.ToString();
}

Должно быть самым быстрым, но я не проверял.

В противном случае вы должны сделать то, что предложил Саймон, и использовать функцию VisualBasic Replace . Это то, что я часто делаю из-за его нечувствительных к регистру возможностей.

string s = "SoftWare";
s = Microsoft.VisualBasic.Strings.Replace(s, "software", "hardware", 1, -1, Constants.vbTextCompare);

Вы должны добавить ссылку на dll Microsoft.VisualBasic.

15 голосов
/ 05 апреля 2011

Это не идеально, но вы можете импортировать Microsoft.VisualBasic и использовать Strings.Replace для этого.В противном случае, я думаю, что это тот случай, когда вы катаетесь самостоятельно или придерживаетесь регулярных выражений.

4 голосов
/ 20 июля 2011

Вот метод расширения. Не уверен, где я его нашел.

public static class StringExtensions
{
    public static string Replace(this string originalString, string oldValue, string newValue, StringComparison comparisonType)
    {
        int startIndex = 0;
        while (true)
        {
            startIndex = originalString.IndexOf(oldValue, startIndex, comparisonType);
            if (startIndex == -1)
                break;

            originalString = originalString.Substring(0, startIndex) + newValue + originalString.Substring(startIndex + oldValue.Length);

            startIndex += newValue.Length;
        }

        return originalString;
    }

}
2 голосов
/ 11 ноября 2016

Это VB.NET-адаптация ответа rboarman выше с необходимыми проверками для нулевых и пустых строк, чтобы избежать бесконечного цикла.

Public Function Replace(ByVal originalString As String, 
                        ByVal oldValue As String, 
                        ByVal newValue As String, 
                        ByVal comparisonType As StringComparison) As String
    If Not String.IsNullOrEmpty(originalString) AndAlso 
       Not String.IsNullOrEmpty(oldValue) AndAlso 
       newValue IsNot Nothing Then
        Dim startIndex As Int32

        Do While True
            startIndex = originalString.IndexOf(oldValue, startIndex, comparisonType)
            If startIndex = -1 Then Exit Do
            originalString = originalString.Substring(0, startIndex) & newValue & 
                             originalString.Substring(startIndex + oldValue.Length)
            startIndex += newValue.Length
        Loop
    End If

    Return originalString
End Function
1 голос
/ 27 апреля 2019

Обновление в .NET Core 2.0+ (август 2017 г.)

Это изначально доступно в .NET Core 2.0 + с String.Replace, которое имеет следующееперегрузки

public string Replace (string oldValue, string newValue, StringComparison comparisonType);
public string Replace (string oldValue, string newValue, bool ignoreCase, System.Globalization.CultureInfo culture);

PS : Вы можете просмотреть исходный код .NET Core , если хотите увидеть, как MS его реализовала

Таким образом, вы можете использовать любой из следующих способов:

"A".Replace("a", "b", StringComparison.CurrentCultureIgnoreCase);
"A".Replace("a", "b", true, CultureInfo.CurrentCulture);

Legacy .NET Framework 4.8 - для проектов VB

Visual Basic имеет Option Compare Настройка, которую можно установить на Binary или Text

Установка на Text сделает все сравнения строк по всему проекту без учета регистра по умолчанию.

Итак, как подсказали другие ответы, если вы набираете Microsoft.VisualBasic.dll, при вызове Strings.Replace, если вы явно не передаете CompareMethod метод будет фактически откладываться до опции Compare для вашего файла или проекта с использованием [OptionCompare] атрибута параметра

Так что любое из следующего также будетork ( опция top доступна только в VB, но оба зависят от VisualBasic.dll )

Option Compare Text

Replace("A","a","b")
Replace("A","a","b", Compare := CompareMethod.Text)
1 голос
/ 21 октября 2016

Мои 2 цента:

public static string Replace(this string originalString, string oldValue, string newValue, StringComparison comparisonType)
{
    if (originalString == null)
        return null;
    if (oldValue == null)
        throw new ArgumentNullException("oldValue");
    if (oldValue == string.Empty)
        return originalString;
    if (newValue == null)
        throw new ArgumentNullException("newValue");

    const int indexNotFound = -1;
    int startIndex = 0, index = 0;
    while ((index = originalString.IndexOf(oldValue, startIndex, comparisonType)) != indexNotFound)
    {
        originalString = originalString.Substring(0, index) + newValue + originalString.Substring(index + oldValue.Length);
        startIndex = index + newValue.Length;
    }

    return originalString;
}



Replace("FOOBAR", "O", "za", StringComparison.OrdinalIgnoreCase);
// "FzazaBAR"

Replace("", "O", "za", StringComparison.OrdinalIgnoreCase);
// ""

Replace("FOO", "BAR", "", StringComparison.OrdinalIgnoreCase);
// "FOO"

Replace("FOO", "F", "", StringComparison.OrdinalIgnoreCase);
// "OO"

Replace("FOO", "", "BAR", StringComparison.OrdinalIgnoreCase);
// "FOO"
0 голосов
/ 13 июня 2014

Я не знаю ни одного готового экземпляра в фреймворке, но вот другая версия метода расширения с минимальным количеством операторов (хотя, возможно, не самая быстрая), для удовольствия.Другие версии функций замены размещены в http://www.codeproject.com/KB/string/fastestcscaseinsstringrep.aspx и ". Есть ли альтернатива string.Резаменитель также нечувствителен к регистру? ".

public static string ReplaceIgnoreCase(this string alterableString, string oldValue, string newValue){
    if(alterableString == null) return null;
    for(
        int i = alterableString.IndexOf(oldValue, System.StringComparison.CurrentCultureIgnoreCase);
        i > -1;
        i = alterableString.IndexOf(oldValue, i+newValue.Length, System.StringComparison.CurrentCultureIgnoreCase)
    ) alterableString =
        alterableString.Substring(0, i)
        +newValue
        +alterableString.Substring(i+oldValue.Length)
    ;
    return alterableString;
}
0 голосов
/ 27 декабря 2013

Вы можете использовать Microsoft.VisualBasic.<em>Strings</em>.<strong>Replace</strong> и передать Microsoft.VisualBasic.<em>CompareMethod</em>.<strong>Text</strong> для замены без учета регистра, например:

Dim myString As String = "One Two Three"
myString = Replace(myString, "two", "TWO", Compare:= CompareMethod.Text)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...