Comment remplacer la * première instance * d'une chaîne dans .NET?


108

Je veux remplacer la première occurrence dans une chaîne donnée.

Comment puis-je accomplir cela dans .NET?


Veuillez publier des messages clairs que les gens peuvent comprendre. J'ai aussi édité celui-ci pour vous. Vous devriez avoir spécifié une langue au moins ici.
GEOCHET

Bien sûr, elle n'est jamais remplacée ... c'est toujours une nouvelle chaîne contenant l'original avec du texte remplacé. C'est parce que les chaînes sont immuables.
Pablo Marambio

J'ai essayé la méthode `String.Replace ()`. mais il remplace tous les "AA" par "XQ"
Thorin Oakenshield

2
cette question - stackoverflow.com/questions/141045/… - révèle tout ce que vous devez faire
stack72

1
Remarque: fusion avec une autre question similaire qui utilisait "AA" => "XQ" comme exemples à rechercher / remplacer.
Marc Gravell

Réponses:


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

Exemple:

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

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

EDIT : Comme @itsmatt l'a mentionné , il y a aussi Regex.Replace (String, String, Int32), qui peut faire la même chose, mais est probablement plus cher à l'exécution, car il utilise un analyseur complet où ma méthode fait une recherche et trois chaînes concaténations.

EDIT2 : S'il s'agit d'une tâche courante, vous souhaiterez peut-être faire de la méthode une méthode d'extension:

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

En utilisant l'exemple ci-dessus, il est maintenant possible d'écrire:

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

2
Intéressant, avez-vous testé votre hypothèse selon laquelle l'approche regex est plus chère à l'exécution? Et la vitesse? Peut-être que la recherche avec Regex est plus rapide qu'avec IndexOf?
mfloryan le

Je préfère un peu la réponse de @BilltheLizard impliquant Remove () et Insert () à cette approche impliquant Substring (). Y a-t-il une raison de dire que l'un est meilleur que l'autre?
JohnC

3
Attention: cela ne fonctionne pas correctement avec Unicode combinant des caractères ou des ligatures. Par exemple, ReplaceFirst("oef", "œ", "i")renvoie incorrectement "ief" au lieu de "if". Voir cette question pour plus d'informations.
Michael Liu

2
ReSharper prévient String.IndexOf is culture specific.. Plus robuste à mettre à jour int pos = text.IndexOf(search, StringComparison.Ordinal);.
Contango

64

Comme itsmatt l'a dit Regex.Replace est un bon choix pour cela, mais pour rendre sa réponse plus complète, je vais la compléter avec un exemple de code:

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

Le troisième paramètre, défini sur 1 dans ce cas, est le nombre d'occurrences du modèle regex que vous souhaitez remplacer dans la chaîne d'entrée à partir du début de la chaîne.

J'espérais que cela pourrait être fait avec une surcharge statique Regex.Replace mais malheureusement, il semble que vous ayez besoin d'une instance Regex pour l'accomplir.


1
Cela fonctionne pour le littéral "foo", mais vous allez vouloir un new Regex(Regex.Escape("foo"))pour le figuratif "foo".
ruffin


15

En tenant compte du «premier seulement», peut-être:

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

?

Ou plus généralement:

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

Ensuite:

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

11
using System.Text.RegularExpressions;

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

trouvera le premier Fdans InputStringet le remplacera par R.


2
Je l'ai simplifié en un one-liner parresult = (New Regex("F")).Replace(InputString, "R", 1)
cjbarth

Meilleure réponse ici (en collaboration avec cjbarth)
Todd Vance

8

Méthode d'extension C # qui fera ceci:

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

Prendre plaisir


Merci! J'ai modifié cela pour créer une méthode d'extension "RemoveFirst" qui ... supprime la première occurrence d'un caractère d'une chaîne.
pbh101

4
Cela échouera si oldValue ne fait pas partie de la chaîne.
VVS

8

Dans la syntaxe C #:

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

4

Et comme il y a aussi VB.NET à considérer, je voudrais offrir:

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

Suppose qu'il AAne doit être remplacé que s'il se trouve au tout début de la chaîne:

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

Si vous devez remplacer la première occurrence de AA, que la chaîne commence par elle ou non, optez pour la solution de Marc.


3

Une des surcharges de Regex.Replaceprend un intpour "Le nombre maximum de fois que le remplacement peut se produire". Évidemment, utiliser Regex.Replacepour le remplacement de texte brut peut sembler exagéré, mais c'est certainement concis:

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

2

Pour tous ceux qui ne se soucient pas d'une référence Microsoft.VisualBasic, il y a la Replaceméthode :

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

1

Cet exemple résume les sous-chaînes (mais est plus lent), mais est probablement beaucoup plus rapide qu'un RegEx:

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

0

Mise à jour de la méthode d'extension permettant Spande minimiser la création de nouvelles chaînes

    public static string ReplaceFirstOccurrence(this string source, string search, string replace) {
        int index = source.IndexOf(search);
        if (index < 0) return source;
        var sourceSpan = source.AsSpan();
        return string.Concat(sourceSpan.Slice(0, index), replace, sourceSpan.Slice(index + search.Length));
    }

-1
string abc = "AAAAX1";

            if(abc.IndexOf("AA") == 0)
            {
                abc.Remove(0, 2);
                abc = "XQ" + abc;
            }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.