Come si sostituisce la * prima istanza * di una stringa in .NET?


108

Voglio sostituire la prima occorrenza in una data stringa.

Come posso farlo in .NET?


Per favore scrivi post chiari che le persone possano capire. Ho modificato anche questo per te. Almeno qui avresti dovuto specificare una lingua.
GEOCHET

Ovviamente non viene mai sostituito ... è sempre una nuova stringa contenente quella originale con testo sostituito. Questo perché le stringhe sono immutabili.
Pablo Marambio

ho provato il metodo `String.Replace ()`. ma sostituisce tutti gli "AA" con "XQ"
Thorin Oakenshield

2
questa domanda - stackoverflow.com/questions/141045/… - rivela tutto ciò che devi fare
stack72

1
Nota: fusione con un'altra domanda simile che utilizzava "AA" => "XQ" come esempi da trovare / sostituire.
Marc Gravell

Risposte:


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);
}

Esempio:

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

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

EDIT : Come menzionato da @itsmatt , c'è anche Regex.Replace (String, String, Int32), che può fare lo stesso, ma è probabilmente più costoso in fase di esecuzione, poiché utilizza un parser completo in cui il mio metodo trova una e tre stringhe concatenazioni.

EDIT2 : se questa è un'attività comune, potresti voler rendere il metodo un metodo di estensione:

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

Utilizzando l'esempio sopra è ora possibile scrivere:

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

2
Interessante, hai testato la tua ipotesi sul fatto che l'approccio regex sia più costoso in fase di esecuzione? E la velocità? Forse la ricerca utilizzando Regex è più veloce rispetto all'utilizzo di IndexOf?
mfloryan

Preferisco la risposta di @BilltheLizard che coinvolge Remove () e Insert () rispetto a questo approccio che coinvolge Substring (). C'è qualche base per dire che uno è migliore dell'altro?
JohnC

3
Attenzione: non funziona correttamente con Unicode che combina caratteri o legature. Ad esempio, ReplaceFirst("oef", "œ", "i")restituisce in modo errato "ief" invece di "if". Vedi questa domanda per maggiori informazioni.
Michael Liu

2
ReSharper avverte String.IndexOf is culture specific.. Più robusto per l'aggiornamento int pos = text.IndexOf(search, StringComparison.Ordinal);.
Contango

64

Come ha detto itsmatt, Regex.Replace è una buona scelta per questo, tuttavia per rendere la sua risposta più completa, lo riempirò con un esempio di codice:

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

Il terzo parametro, impostato su 1 in questo caso, è il numero di occorrenze del pattern regex che si desidera sostituire nella stringa di input dall'inizio della stringa.

Speravo che questo potesse essere fatto con un sovraccarico di Regex.Replace statico, ma sfortunatamente sembra che sia necessaria un'istanza Regex per realizzarlo.


1
Funziona per letterale "foo", ma vorrai un new Regex(Regex.Escape("foo"))figurativo "foo".
ruffin


15

Tenendo conto del "primo solo", forse:

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

?

O più in generale:

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);
}

Poi:

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

11
using System.Text.RegularExpressions;

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

troverà il primo Fin InputStringe lo sostituirà con R.


2
L'ho semplificato in una battuta diresult = (New Regex("F")).Replace(InputString, "R", 1)
cjbarth,

La migliore risposta qui (in collaborazione con cjbarth)
Todd Vance

8

Metodo di estensione C # che farà questo:

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);    
    } 
}

Godere


Grazie! L'ho modificato per creare un metodo di estensione "RemoveFirst" che ... rimuove la prima occorrenza di un carattere da una stringa.
pbh101

4
Questo fallirà se oldValue non fa parte della stringa.
VVS

8

Nella sintassi C #:

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

4

E poiché c'è anche VB.NET da considerare, vorrei offrire:

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

Presuppone che AAdebba essere sostituito solo se si trova all'inizio della stringa:

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

Se è necessario sostituire la prima occorrenza di AA, indipendentemente dal fatto che la stringa inizi o meno con essa, andare con la soluzione di Marc.


3

Uno dei sovraccarichi di Regex.Replaceprende un intper "Il numero massimo di volte che la sostituzione può avvenire". Ovviamente, l'uso Regex.Replaceper la sostituzione del testo normale può sembrare eccessivo, ma è certamente conciso:

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

2

Per chiunque non dispiaccia un riferimento a Microsoft.VisualBasic, c'è il ReplaceMetodo :

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

1

Questo esempio astrae le sottostringhe (ma è più lento), ma probabilmente è molto più veloce di una 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;
            }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.