Как заменить часть строки позицией? - PullRequest
134 голосов
/ 16 февраля 2011

У меня есть эта строка: ABCDEFGHIJ

Мне нужно заменить из положения 4 в положение 5 строкой ZX

Это будет выглядеть так: ABCZXFGHIJ

Но не использовать с string.replace("DE","ZX") - мне нужно использовать с position

Как я могу это сделать?

Ответы [ 16 ]

2 голосов
/ 15 мая 2014

С помощью этого поста я создаю следующую функцию с дополнительными проверками длины

public string ReplaceStringByIndex(string original, string replaceWith, int replaceIndex)
{
    if (original.Length >= (replaceIndex + replaceWith.Length))
    {
        StringBuilder rev = new StringBuilder(original);
        rev.Remove(replaceIndex, replaceWith.Length);
        rev.Insert(replaceIndex, replaceWith);
        return rev.ToString();
    }
    else
    {
        throw new Exception("Wrong lengths for the operation");
    }
}
1 голос
/ 05 января 2019

Если вы заботитесь о производительности, то здесь вам нужно избегать распределения. А если вы используете .Net Core 2.1+ (или, пока не выпущенный, .Net Standard 2.1), то вы можете, используя метод string.Create :

public static string ReplaceAt(this string str, int index, int length, string replace)
{
    return string.Create(str.Length - length + replace.Length, (str, index, length, replace),
        (span, state) =>
        {
            state.str.AsSpan().Slice(0, state.index).CopyTo(span);
            state.replace.AsSpan().CopyTo(span.Slice(state.index));
            state.str.AsSpan().Slice(state.index + state.length).CopyTo(span.Slice(state.index + state.replace.Length));
        });
}

Этот подход сложнее для понимания, чем альтернативы, но он единственный, который выделяет только один объект на вызов: вновь созданная строка.

0 голосов
/ 16 марта 2019
string myString = "ABCDEFGHIJ";
string modifiedString = new StringBuilder(myString){[3]='Z', [4]='X'}.ToString();

Позвольте мне объяснить мое решение.
Учитывая постановку задачи об изменении строки в двух ее конкретных позициях («от позиции 4 до позиции 5») с двумя символами «Z» и «X», и предлагается использовать индекс позиции для изменения строки, а не строки. Replace ( ) (возможно, из-за возможности повторения некоторых символов в реальной строке), я бы предпочел использовать минималистский подход для достижения цели, вместо использования Substring() и строки Concat() или строки Remove() и Insert() подход. Хотя все эти решения будут служить цели в достижении той же цели, но это зависит только от личного выбора и философии урегулирования с минималистским подходом.
Возвращаясь к вышеупомянутому решению, если мы рассмотрим string и StringBuilder, они оба внутренне воспримут данную строку как массив символов. Если мы посмотрим на реализацию StringBuilder, она поддерживает внутреннюю переменную, например «internal char[] m_ChunkChars;», для захвата данной строки. Теперь, поскольку это внутренняя переменная, мы не можем напрямую обращаться к ней. Для внешнего мира, чтобы иметь возможность получить доступ и изменить этот массив символов, StringBuilder предоставляет их через свойство indexer, которое выглядит примерно так:

    [IndexerName("Chars")]
    public char this[int index]
    {
      get
      {
        StringBuilder stringBuilder = this;
        do
        {
          // … some code
            return stringBuilder.m_ChunkChars[index1];
          // … some more code
        }
      }
      set
      {
        StringBuilder stringBuilder = this;
        do
        {
            //… some code
            stringBuilder.m_ChunkChars[index1] = value;
            return;
            // …. Some more code
        }
      }
    }

Мое решение, упомянутое выше, использует эту возможность индексатора для непосредственного изменения внутреннего символьного массива, который IMO эффективен и минималистичен.

КСТАТИ; мы можем переписать вышеприведенное решение более детально, как показано ниже:

 string myString = "ABCDEFGHIJ";
 StringBuilder tempString = new StringBuilder(myString);
 tempString[3] = 'Z';
 tempString[4] = 'X';
 string modifiedString = tempString.ToString();

В этом контексте также хотелось бы отметить, что в случае string он также имеет свойство indexer как средство для представления своего внутреннего символьного массива, но в этом случае он имеет только свойство Getter (и не Setter), так как строка неизменный в природе. И именно поэтому нам нужно использовать StringBuilder для изменения массива символов.

[IndexerName("Chars")]
public extern char this[int index] { [SecuritySafeCritical, __DynamicallyInvokable, MethodImpl(MethodImplOptions.InternalCall)] get; }

И, наконец, что не менее важно, это решение лучше всего подходит для этой конкретной проблемы, когда требуется заменить только несколько символов с заранее известным индексом позиции. Это может не подходить лучше всего, когда требуется изменить довольно длинную строку, т. Е. Количество символов для изменения велико.

0 голосов
/ 28 марта 2018

Я искал решение со следующими требованиями:

  1. использовать только одно однострочное выражение
  2. использовать только системные встроенные методы (без пользовательских утилит)

Раствор 1

Решение, которое больше всего подходит мне, таково:

// replace `oldString[i]` with `c`
string newString = new StringBuilder(oldString).Replace(oldString[i], c, i, 1).ToString();

Используется StringBuilder.Replace(oldChar, newChar, position, count)

Решение 2

Другим решением, удовлетворяющим моим требованиям, является использование Substring с конкатенацией:

string newString = oldStr.Substring(0, i) + c + oldString.Substring(i+1, oldString.Length);

Это тоже нормально. Я догадываюсь это не так эффективно, как первое в плане производительности (из-за ненужной конкатенации строк). Но преждевременная оптимизация - корень всех зол .

Итак, выберите тот, который вам нравится больше всего:)

0 голосов
/ 30 января 2017

Лучше использовать String.substr().

Как это:

ReplString = GivenStr.substr(0, PostostarRelStr)
           + GivenStr(PostostarRelStr, ReplString.lenght());
0 голосов
/ 31 августа 2013

Я полагаю, что самый простой способ был бы таким: (без stringbuilder)

string myString = "ABCDEFGHIJ";
char[] replacementChars = {'Z', 'X'};
byte j = 0;

for (byte i = 3; i <= 4; i++, j++)  
{                   
myString = myString.Replace(myString[i], replacementChars[j]);  
}

Это работает, потому что переменная типа string может рассматриваться как массив переменных типа char. Например, вы можете ссылаться на второй символ строковой переменной с именем «myString» как myString [1]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...