Як замінити * перший екземпляр * рядка в .NET?


108

Я хочу замінити перше виникнення в заданому рядку.

Як я можу досягти цього в .NET?


Будь ласка, викладіть чіткі повідомлення, які люди можуть зрозуміти. Я редагував і цей для вас. Ви повинні вказати мову хоча б тут.
ГЕОЧЕТ

Звичайно, він ніколи не замінюється ... це завжди нова рядок, що містить оригінальний із заміненим текстом. Це тому, що струна незмінна.
Пабло Марамбіо

я спробував метод `String.Replace ()`. але він замінює всі "AA" на "XQ"
Thorin Oakenshield

2
це питання - stackoverflow.com/questions/141045/… - розкриває все, що вам потрібно зробити
stack72

1
Примітка: об'єднання з іншим подібним запитанням, яке використовувало "AA" => "XQ" в якості прикладів для пошуку / заміни.
Марк Гравелл

Відповіді:


134
string ReplaceFirst(string text, string search, string replace)
{
  int pos = text.IndexOf(search);
  if (pos < 0)
  {
    return text;
  }
  return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}

Приклад:

string str = "The brown brown fox jumps over the lazy dog";

str = ReplaceFirst(str, "brown", "quick");

EDIT : Як згадував @itsmatt , є також Regex.Replace (String, String, Int32), який може робити те саме, але, ймовірно, дорожчий під час виконання, оскільки він використовує повнофункціональний синтаксичний аналізатор, де в моєму методі знайдеться і три рядки конкатенації.

EDIT2 : Якщо це звичайне завдання, можливо, ви хочете зробити метод методом розширення:

public static class StringExtension
{
  public static string ReplaceFirst(this string text, string search, string replace)
  {
     // ...same as above...
  }
}

За допомогою наведеного вище прикладу тепер можна написати:

str = str.ReplaceFirst("brown", "quick");

2
Цікаво, чи ви перевіряли ваші припущення щодо того, що підхід регулярного видобутку дорожчий під час виконання? Як щодо швидкості? Можливо, пошук за допомогою Regex швидший, ніж використання IndexOf?
mfloryan

Я якось віддаю перевагу відповіді @BilltheLizard, що стосується Remove () та Insert () над цим підходом із використанням Substring (). Чи є підстава сказати, що один кращий за інший?
JohnC

3
Остерігайтеся: це не працює належним чином, якщо Unicode поєднує символи чи лігатури. Наприклад, ReplaceFirst("oef", "œ", "i")неправильно повертається "ief" замість "if". Дивіться це питання для отримання додаткової інформації.
Майкл Лю

2
ReSharper попереджає String.IndexOf is culture specific.. Більш надійне оновлення до int pos = text.IndexOf(search, StringComparison.Ordinal);.
Контанго

64

Як itsmatt сказав Regex.Replace є хорошим вибором для цього , однак , щоб зробити його відповідь повнішим , я заповню її зі зразком коду:

using System.Text.RegularExpressions;
...
Regex regex = new Regex("foo");
string result = regex.Replace("foo1 foo2 foo3 foo4", "bar", 1);             
// result = "bar1 foo2 foo3 foo4"

Третій параметр, встановлений в даному випадку 1, - це кількість зустрічань шаблону регулярних виразів, які ви хочете замінити у вхідній рядку з початку рядка.

Я сподівався, що це можна зробити за допомогою статичного перевантаження Regex.Replace, але, на жаль, здається, що для його виконання потрібен екземпляр Regex.


1
Це працює в прямому сенсі "foo", але ви хочете new Regex(Regex.Escape("foo"))образне "foo".
ruffin


15

Враховуючи "лише перший", можливо:

int index = input.IndexOf("AA");
if (index >= 0) output = input.Substring(0, index) + "XQ" +
     input.Substring(index + 2);

?

Або загалом:

public static string ReplaceFirstInstance(this string source,
    string find, string replace)
{
    int index = source.IndexOf(find);
    return index < 0 ? source : source.Substring(0, index) + replace +
         source.Substring(index + find.Length);
}

Тоді:

string output = input.ReplaceFirstInstance("AA", "XQ");

11
using System.Text.RegularExpressions;

RegEx MyRegEx = new RegEx("F");
string result = MyRegex.Replace(InputString, "R", 1);

знайти перший Fв InputStringі замінити його R.


2
Я спростив його до result = (New Regex("F")).Replace(InputString, "R", 1)
одноводкового

Найкраща відповідь тут (спільно з cjbarth)
Todd Vance

8

C # метод розширення, який буде робити це:

public static class StringExt
{
    public static string ReplaceFirstOccurrence(this string s, string oldValue, string newValue)
    {
         int i = s.IndexOf(oldValue);
         return s.Remove(i, oldValue.Length).Insert(i, newValue);    
    } 
}

Насолоджуйтесь


Дякую! Я змінив це, щоб зробити метод розширення "RemoveFirst", який ... видаляє перше виникнення символу з рядка.
pbh101

4
Це не вдасться, якщо oldValue не входить у рядок.
VVS

8

У синтаксисі C #:

int loc = original.IndexOf(oldValue);
if( loc < 0 ) {
    return original;
}
return original.Remove(loc, oldValue.Length).Insert(loc, newValue);

4

А оскільки є також VB.NET для розгляду, я хотів би запропонувати:

Private Function ReplaceFirst(ByVal text As String, ByVal search As String, ByVal replace As String) As String
    Dim pos As Integer = text.IndexOf(search)
    If pos >= 0 Then
        Return text.Substring(0, pos) + replace + text.Substring(pos + search.Length)
    End If
    Return text 
End Function

4

Припускає, що AAйого потрібно замінити лише в тому випадку, якщо він знаходиться на самому початку рядка:

var newString;
if(myString.StartsWith("AA"))
{
  newString ="XQ" + myString.Substring(2);
}

Якщо вам потрібно замінити перше виникнення AA, починаючи з нього рядок чи ні, перейдіть з рішенням від Marc.


3

Одне з перевантажень Regex.Replaceзаймає значення int"Максимальна кількість разів, коли може відбутися заміна". Очевидно, що використання Regex.Replaceдля простої заміни тексту може здатися надмірним, але це, звичайно, стисло:

string output = (new Regex("AA")).Replace(input, "XQ", 1);

2

Для всіх, хто не заперечує посилання Microsoft.VisualBasic, існує Replaceметод :

string result = Microsoft.VisualBasic.Strings.Replace("111", "1", "0", 2, 1); // "101"

1

Цей приклад абстрагує підрядки (але повільніше), але, ймовірно, набагато швидший, ніж RegEx:

var parts = contents.ToString().Split(new string[] { "needle" }, 2, StringSplitOptions.None);
return parts[0] + "replacement" + parts[1];

-1
string abc = "AAAAX1";

            if(abc.IndexOf("AA") == 0)
            {
                abc.Remove(0, 2);
                abc = "XQ" + abc;
            }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.