@TotZam - пожалуйста, проверьте даты. Этот старше, чем тот, который вы связали.
ToolmakerSteve
@ToolmakerSteve я обычно смотрю на качество вопроса и ответов, а не даты, как сказал сделать здесь . В этом случае я, похоже, допустил ошибку и нажал не ту, чтобы пометить как дубликат, поскольку качество этого вопроса, очевидно, лучше, и поэтому я пометил другой вопрос.
Тот Зам
@TotZam - ах, я не знал об этой рекомендации - спасибо за указание на это. (Хотя кажется странным, что что-то более старое сообщается как дубликат чего-то более нового, в таком случае стоило бы явно объяснить, что вы помечаете как дубликат вопроса СТАРЫЕ, потому что у связанного есть лучшие ответы.)
ToolmakerSteve
Ответы:
198
Самый простой способ добавить и удалить диапазоны в строке - использовать StringBuilder.
var theString ="ABCDEFGHIJ";var aStringBuilder =newStringBuilder(theString);
aStringBuilder.Remove(3,2);
aStringBuilder.Insert(3,"ZX");
theString = aStringBuilder.ToString();
Альтернативой является использование String.Substring, но я думаю, что StringBuilderкод становится более читабельным.
Почему вы используете StringBuilder здесь? Проверьте ответ V4Vendetta, который является намного более читабельным ...
Fortega
1
@Fortega Remove () и Insert () каждый создает и возвращает новую строку. Подход StringBuilder позволяет избежать этих дополнительных затрат, работая в заранее выделенном разделе памяти и перемещая вокруг него символы.
Redcalx
@redcalx Это правда, но дополнительные затраты вводятся за счет введения объекта
StringBuilder
2
Какой смысл использовать StringBuilder здесь, если вы вызываете Remove и Insert так же, как V4Vendetta, но он делает это прямо в строке? Кажется, избыточный код.
metaududdy
186
string s ="ABCDEFGH";
s= s.Remove(3,2).Insert(3,"ZX");
Я предпочитаю это, чем инициализировать новый StringBuilder (...). Спасибо!
Майкл Норгрен
3
Я не знаю, почему кто-то будет использовать stringbuilder для этой операции. Это хороший ответ
NappingRabbit
43
ReplaceAt (индекс int, длина int, замена строки)
Вот метод расширения, который не использует StringBuilder или Substring. Этот метод также позволяет замещающей строке выходить за пределы длины исходной строки.
//// str - the source string//// index- the start location to replace at (0-based)//// length - the number of characters to be removed before inserting//// replace - the string that is replacing characterspublicstaticstringReplaceAt(thisstring str,int index,int length,string replace){return str.Remove(index,Math.Min(length, str.Length- index)).Insert(index, replace);}
При использовании этой функции, если вы хотите, чтобы вся замещающая строка заменяла как можно больше символов, установите длину равной длине замещающей строки:
Я предполагаю, что это более эффективно, поскольку класс StringBuilder не нужно инициализировать и поскольку он использует более простые операции. Пожалуйста, поправьте меня, если я ошибаюсь. :)
Stringbuilder более эффективен, если длина строки превышает, скажем, 200 символов.
Тим Шмельтер,
Нет стресса. Работал прямо. Спасибо
D_Edet
9
Используйте String.Substring()(подробности здесь ), чтобы вырезать левую часть, затем замену, затем правую часть. Играйте с индексами, пока не поймете как надо :)
Я создал три метода, используя три вышеупомянутых метода (string.Remove / Insert, Stringbuilder.Remove / Insert и ответ подстроки Даниэля, и SubString был самым быстрым методом.
Это работает, вы, вероятно, не хотите tвозвращать снова.
Пьер
4
Если вы заботитесь о производительности, то здесь вам нужно избегать распределения. И если вы на .Net Ядра 2.1+ (или, еще не издававшийся, .Net стандарт 2.1), то вы можете, используя в string.Createметод :
Все остальные ответы не работают, если строка содержит символ Unicode (например, Emojis), потому что символ Unicode весит больше байтов, чем символ.
Пример : смайлики '🎶', преобразованные в байты, будут весить эквивалент 2 символов. Таким образом, если символ unicode находится в начале вашей строки, offsetпараметр будет смещен).
В этом разделе я расширяю класс StringInfo до Replace, сохраняя положение алгоритма Ника Миллера, чтобы избежать этого:
dotnetfiddle.net/l0dqS5 Я не мог заставить другие методы потерпеть неудачу на Unicode. Пожалуйста, измените скрипку, чтобы продемонстрировать ваш вариант использования. Очень заинтересованы в результатах.
Маркус
1
@MarkusHooge Попробуйте разместить символы Unicode в начале вашей строки, например: dotnetfiddle.net/3V2K3Y . Вы увидите, что работает только последняя строка, и поместите символ на 4-е место (в другом случае, символ unicode занимает длину 2 символа)
GGO
Вы правы, это не ясно. Я обновил свой ответ, чтобы добавить больше объяснений, почему другие ответы не работают
GGO
1
Я искал решение со следующими требованиями:
использовать только одно однострочное выражение
использовать только системные встроенные методы (нет пользовательских утилит)
Решение 1
Решение, которое лучше всего подходит мне, это:
// replace `oldString[i]` with `c`string newString =newStringBuilder(oldString).Replace(oldString[i], c, i,1).ToString();
Другое решение, которое удовлетворяет моим требованиям, заключается в использовании Substringс конкатенацией:
string newString = oldStr.Substring(0, i)+ c + oldString.Substring(i+1, oldString.Length);
Это тоже нормально. Я думаю, что это не так эффективно, как в первом случае с производительностью (из-за ненужной конкатенации строк). Но преждевременная оптимизация - корень всего зла .
Так что выбирайте тот, который вам нравится больше всего :)
Позвольте мне объяснить мое решение.
Учитывая постановку задачи об изменении строки в двух ее конкретных положениях («от позиции 4 до позиции 5») с двумя символами «Z» и «X», и предлагается использовать индекс позиции для изменения строки, а не строки. Replace ( ) метод (может быть из-за возможности повторения некоторых символов в реальной строке), я бы предпочел использовать минималистский подход для достижения цели по сравнению с использованием Substring()и строки Concat()или строки Remove()и Insert()подхода. Хотя все эти решения будут служить цели в достижении той же цели, но это зависит только от личного выбора и философии урегулирования с минималистским подходом.
Возвращаясь к моему решению, упомянутому выше, если мы рассмотрим подробнееstring иStringBuilderоба они внутренне обрабатывают данную строку как массив символов. Если мы посмотрим на реализацию, то StringBuilderона поддерживает внутреннюю переменную, похожую на « internal char[] m_ChunkChars;», для захвата заданной строки. Теперь, поскольку это внутренняя переменная, мы не можем напрямую обращаться к ней. Для внешнего мира, чтобы иметь возможность получить доступ и изменить этот массив символов, StringBuilderпредоставляет их через свойство indexer, которое выглядит примерно так:
[IndexerName("Chars")]publiccharthis[int index]{get{StringBuilder stringBuilder =this;do{// … some codereturn 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этого также есть свойство indexer как средство для раскрытия своего внутреннего символьного массива, но в этом случае у него есть только свойство Getter (и нет Setter), поскольку строка является неизменяемой по своей природе. И именно поэтому мы должны использовать, StringBuilderчтобы изменить массив символов.
И последнее, но не менее важное: это решение лучше всего подходит для этой конкретной проблемы, когда требуется заменить только несколько символов с заранее известным индексом позиции. Это может быть не лучшим вариантом, когда требуется изменить довольно длинную строку, т. Е. Количество символов для изменения велико.
Я считаю, что самый простой способ был бы так: (без 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]
Это работает только потому, что в примере автора stringзаменяемые символы встречаются только один раз. Если вы столкнетесь с этим, скажем, "DBCDEFGHIE"тогда вы получите "ZBCZXFGHIX", что не является желаемым результатом. Кроме того, я не согласен, что это проще, чем другие не- StringBuilderрешения, которые были опубликованы два с половиной года назад.
Ответы:
Самый простой способ добавить и удалить диапазоны в строке - использовать
StringBuilder
.Альтернативой является использование
String.Substring
, но я думаю, чтоStringBuilder
код становится более читабельным.источник
источник
ReplaceAt (индекс int, длина int, замена строки)
Вот метод расширения, который не использует StringBuilder или Substring. Этот метод также позволяет замещающей строке выходить за пределы длины исходной строки.
При использовании этой функции, если вы хотите, чтобы вся замещающая строка заменяла как можно больше символов, установите длину равной длине замещающей строки:
В противном случае вы можете указать количество символов, которые будут удалены:
Если вы укажете, что длина равна 0, то эта функция действует как функция вставки:
Я предполагаю, что это более эффективно, поскольку класс StringBuilder не нужно инициализировать и поскольку он использует более простые операции. Пожалуйста, поправьте меня, если я ошибаюсь. :)
источник
Используйте
String.Substring()
(подробности здесь ), чтобы вырезать левую часть, затем замену, затем правую часть. Играйте с индексами, пока не поймете как надо :)Что-то вроде:
источник
Как метод расширения.
источник
источник
t
возвращать снова.Если вы заботитесь о производительности, то здесь вам нужно избегать распределения. И если вы на .Net Ядра 2.1+ (или, еще не издававшийся, .Net стандарт 2.1), то вы можете, используя в
string.Create
метод :Этот подход сложнее для понимания, чем альтернативы, но он единственный, который выделяет только один объект на вызов: вновь созданная строка.
источник
Вы можете попробовать что-нибудь связать это:
источник
Как и другие упомянули,
Substring()
функция существует по причине:Также я рассчитал это против
StringBuilder
решения и получил 900 тиков против 875. Так что это немного медленнее.источник
"ABCDEFGHIJ"
и"ZX"
разной длины.Еще один
источник
С помощью этого поста я создаю следующую функцию с дополнительными проверками длины
источник
Все остальные ответы не работают, если строка содержит символ Unicode (например, Emojis), потому что символ Unicode весит больше байтов, чем символ.
В этом разделе я расширяю класс StringInfo до Replace, сохраняя положение алгоритма Ника Миллера, чтобы избежать этого:
источник
Я искал решение со следующими требованиями:
Решение 1
Решение, которое лучше всего подходит мне, это:
Это использует
StringBuilder.Replace(oldChar, newChar, position, count)
Решение 2
Другое решение, которое удовлетворяет моим требованиям, заключается в использовании
Substring
с конкатенацией:Это тоже нормально. Я думаю, что это не так эффективно, как в первом случае с производительностью (из-за ненужной конкатенации строк). Но преждевременная оптимизация - корень всего зла .
Так что выбирайте тот, который вам нравится больше всего :)
источник
Лучше использовать
String.substr()
.Как это:
источник
Позвольте мне объяснить мое решение.
Учитывая постановку задачи об изменении строки в двух ее конкретных положениях («от позиции 4 до позиции 5») с двумя символами «Z» и «X», и предлагается использовать индекс позиции для изменения строки, а не строки. Replace ( ) метод (может быть из-за возможности повторения некоторых символов в реальной строке), я бы предпочел использовать минималистский подход для достижения цели по сравнению с использованием
Substring()
и строкиConcat()
или строкиRemove()
иInsert()
подхода. Хотя все эти решения будут служить цели в достижении той же цели, но это зависит только от личного выбора и философии урегулирования с минималистским подходом.Возвращаясь к моему решению, упомянутому выше, если мы рассмотрим подробнее
string
иStringBuilder
оба они внутренне обрабатывают данную строку как массив символов. Если мы посмотрим на реализацию, тоStringBuilder
она поддерживает внутреннюю переменную, похожую на «internal char[] m_ChunkChars;
», для захвата заданной строки. Теперь, поскольку это внутренняя переменная, мы не можем напрямую обращаться к ней. Для внешнего мира, чтобы иметь возможность получить доступ и изменить этот массив символов,StringBuilder
предоставляет их через свойство indexer, которое выглядит примерно так:Мое решение, упомянутое выше, использует эту возможность индексатора для непосредственного изменения внутреннего символьного массива, который IMO эффективен и минималистичен.
КСТАТИ; мы можем переписать вышеприведенное решение более подробно, например, ниже
В этом контексте также хотелось бы упомянуть, что в случае
string
этого также есть свойство indexer как средство для раскрытия своего внутреннего символьного массива, но в этом случае у него есть только свойство Getter (и нет Setter), поскольку строка является неизменяемой по своей природе. И именно поэтому мы должны использовать,StringBuilder
чтобы изменить массив символов.И последнее, но не менее важное: это решение лучше всего подходит для этой конкретной проблемы, когда требуется заменить только несколько символов с заранее известным индексом позиции. Это может быть не лучшим вариантом, когда требуется изменить довольно длинную строку, т. Е. Количество символов для изменения велико.
источник
источник
Вот простой метод расширения:
Используйте это так:
источник
Я считаю, что самый простой способ был бы так: (без stringbuilder)
Это работает, потому что переменная типа string может рассматриваться как массив переменных типа char. Например, вы можете ссылаться на второй символ строковой переменной с именем «myString» как myString [1]
источник
string
заменяемые символы встречаются только один раз. Если вы столкнетесь с этим, скажем,"DBCDEFGHIE"
тогда вы получите"ZBCZXFGHIX"
, что не является желаемым результатом. Кроме того, я не согласен, что это проще, чем другие не-StringBuilder
решения, которые были опубликованы два с половиной года назад.