it-swarm.com.de

Wie ersetze ich einen Teil des Strings durch die Position?

Ich habe diese Zeichenfolge: ABCDEFGHIJ

Ich muss von Position 4 bis Position 5 durch die Zeichenfolge ZX ersetzen.

Es wird so aussehen: ABCZXFGHIJ

Aber nicht mit string.replace("DE","ZX") zu verwenden - ich muss mit position verwenden

Wie kann ich es tun?

125
Gali

Die einfachste Möglichkeit zum Hinzufügen und Entfernen von Bereichen in einer Zeichenfolge besteht in der Verwendung der StringBuilder .

var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();

Eine Alternative ist die Verwendung von String.Substring , aber ich denke, der StringBuilder-Code wird lesbarer.

168
Albin Sunnanbo
string s = "ABCDEFGH";
s= s.Remove(3, 2).Insert(3, "ZX");
145
V4Vendetta

ReplaceAt (int Index, Int Länge, String ersetzen)

Hier ist eine Erweiterungsmethode, die StringBuilder oder Substring nicht verwendet. Mit dieser Methode kann die Ersatzzeichenfolge auch über die Länge der Quellzeichenfolge hinaus verlängert werden.

//// 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 characters
public static string ReplaceAt(this string str, int index, int length, string replace)
{
    return str.Remove(index, Math.Min(length, str.Length - index))
            .Insert(index, replace);
}

Wenn Sie bei Verwendung dieser Funktion möchten, dass die gesamte Ersetzungszeichenfolge so viele Zeichen wie möglich ersetzt, setzen Sie die Länge auf die Länge der Ersetzungszeichenfolge:

"0123456789".ReplaceAt(7, 5, "Hello") = "0123456Hello"

Andernfalls können Sie die Anzahl der Zeichen angeben, die entfernt werden sollen:

"0123456789".ReplaceAt(2, 2, "Hello") = "01Hello456789"

Wenn Sie als Länge 0 angeben, verhält sich diese Funktion wie die Einfügefunktion:

"0123456789".ReplaceAt(4, 0, "Hello") = "0123Hello456789"

Ich denke, das ist effizienter, da die StringBuilder-Klasse nicht initialisiert werden muss und mehr grundlegende Operationen benötigt. Bitte korrigieren Sie mich, wenn ich falsch liege. :)

32
Nick Miller

Verwenden Sie String.Substring() (Details hier ), um den linken Teil zu schneiden, dann Ihren Ersatz und dann den rechten Teil. Spiele mit Indexen, bis du es richtig verstanden hast :)

So etwas wie:

string replacement=original.Substring(0,start)+
    rep+original.Substring(start+rep.Length);
9

Als Erweiterungsmethode.

public static class StringBuilderExtension
{
    public static string SubsituteString(this string OriginalStr, int index, int length, string SubsituteStr)
    {
        return new StringBuilder(OriginalStr).Remove(index, length).Insert(index, SubsituteStr).ToString();
    }
}
6
alykhalid
        string s = "ABCDEFG";
        string t = "st";
        s = s.Remove(4, t.Length);
        s = s.Insert(4, t);
5
Javed Akram

Du könntest etwas Link versuchen:

string str = "ABCDEFGHIJ";
str = str.Substring(0, 2) + "ZX" + str.Substring(5);
3
MBU

Wie bereits erwähnt, gibt es die Funktion Substring() aus einem bestimmten Grund:

static void Main(string[] args)
{
    string input = "ABCDEFGHIJ";

    string output = input.Overwrite(3, "ZX"); // 4th position has index 3
    // ABCZXFGHIJ
}

public static string Overwrite(this string text, int position, string new_text)
{
    return text.Substring(0, position) + new_text + text.Substring(position + new_text.Length);
}

Ich habe dies auch gegen die StringBuilder-Lösung getimet und 900 Tics vs. 875 erhalten. Es ist also etwas langsamer.

3
ja72

Alle anderen Antworten funktionieren nicht, wenn die Zeichenfolge Unicode-Zeichen enthält (wie Emojis).

Mit this topic erweitere ich die StringInfo-Klasse zu Replace by Position, wobei der Nick Miller-Algorithmus beibehalten wird:

public static class StringInfoUtils
{
    public static string ReplaceByPosition(this string str, string replaceBy, int offset, int count)
    {
        return new StringInfo(str).ReplaceByPosition(replaceBy, offset, count).String;
    }

    public static StringInfo ReplaceByPosition(this StringInfo str, string replaceBy, int offset, int count)
    {
        return str.RemoveByTextElements(offset, count).InsertByTextElements(offset, replaceBy);
    }

    public static StringInfo RemoveByTextElements(this StringInfo str, int offset, int count)
    {
        return new StringInfo(string.Concat(
            str.SubstringByTextElements(0, offset),
            offset + count < str.LengthInTextElements
                ? str.SubstringByTextElements(offset + count, str.LengthInTextElements - count - offset)
                : ""
            ));
    }
    public static StringInfo InsertByTextElements(this StringInfo str, int offset, string insertStr)
    {
        if (string.IsNullOrEmpty(str?.String))
            return new StringInfo(insertStr);
        return new StringInfo(string.Concat(
            str.SubstringByTextElements(0, offset),
            insertStr,
            str.LengthInTextElements - offset > 0 ? str.SubstringByTextElements(offset, str.LengthInTextElements - offset) : ""
        ));
    }
}
3
GGO

Mit Hilfe dieses Beitrags erstelle ich folgende Funktion mit zusätzlichen Längenkontrollen

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");
    }
}
2
Hassan

Noch ein anderer

    public static string ReplaceAtPosition(this string self, int position, string newValue)        
    {
        return self.Remove(position, newValue.Length).Insert(position, newValue); 
    }
2

Ich habe nach einer Lösung mit folgenden Anforderungen gesucht:

  1. verwenden Sie nur einen einzeiligen Ausdruck
  2. nur systemintegrierte Methoden verwenden (kein benutzerdefiniertes implementiertes Dienstprogramm)

Lösung 1

Die Lösung, die am besten zu mir passt, ist folgende:

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

Dies verwendet StringBuilder.Replace(oldChar, newChar, position, count)

Lösung 2

Die andere Lösung, die meine Anforderungen erfüllt, ist die Verwendung von Substring mit Verkettung:

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

Das ist auch OK. Ich rate ist nicht so effizient wie die erste Performance (wegen unnötiger Verkettung von Strings). Aber vorzeitige Optimierung ist die Wurzel allen Übels

Wählen Sie also die aus, die Ihnen am besten gefällt :)

0
KFL
string myString = "ABCDEFGHIJ";
string modifiedString = new StringBuilder(myString){[3]='Z', [4]='X'}.ToString();

Lassen Sie mich meine Lösung erklären.
Angesichts der Problemstellung, dass eine Zeichenfolge an ihren beiden spezifischen Positionen („Position 4 bis Position 5“) mit den beiden Zeichen „Z“ und „X“ geändert werden muss, besteht die Aufforderung darin, den Positionsindex zu verwenden, um die Zeichenfolge zu ändern und nicht die Methode string Replace () (möglicherweise aufgrund der Möglichkeit der Wiederholung einiger Zeichen in der tatsächlichen Zeichenfolge). Ich würde es vorziehen, einen minimalistischen Ansatz zu verwenden, um das Ziel zu erreichen, anstatt Substring() und string Concat() oder string Remove() und Insert(). Alle diese Lösungen werden zwar dem Ziel dienen, dasselbe Ziel zu erreichen, es hängt jedoch nur von der persönlichen Wahl und der Philosophie ab, sich mit einem minimalistischen Ansatz abzufinden.
Kommen wir zu meiner obigen Lösungserwähnung zurück. Wenn wir uns string und StringBuilder genauer ansehen, behandeln beide intern eine bestimmte Zeichenfolge als ein Array von Zeichen. Wenn wir uns die Implementierung von StringBuilder ansehen, wird eine interne Variable wie "internal char[] m_ChunkChars;" verwaltet, um die angegebene Zeichenfolge zu erfassen. Da dies nun eine interne Variable ist, können wir nicht direkt auf dieselbe zugreifen. Damit die Außenwelt auf dieses Zeichenarray zugreifen und es ändern kann, macht StringBuilder sie über die Indexereigenschaft verfügbar, die etwa wie folgt aussieht

    [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
        }
      }
    }

Meine oben erwähnte Lösung nutzt diese Indexer-Fähigkeit, um das intern verwaltete Zeichen-Array, das IMO effizient und minimalistisch ist, direkt zu ändern.

BTW; wir können die obige Lösung etwas aufwendiger umschreiben als unten

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

In diesem Zusammenhang möchte ich auch erwähnen, dass es im Fall von string auch eine Indexereigenschaft hat, um sein internes Zeichenarray verfügbar zu machen, aber in diesem Fall hat es nur die Getter-Eigenschaft (und keinen Setter), da die Zeichenfolge von Natur aus unveränderlich ist. Deshalb müssen wir StringBuilder verwenden, um das Zeichenarray zu ändern.

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

Und last but not least ist diese Lösung am besten für dieses spezielle Problem geeignet, bei dem nur wenige Zeichen durch einen bekannten Positionsindex im Voraus ersetzt werden müssen. Es ist möglicherweise nicht die beste Anpassung, wenn die Anforderung darin besteht, eine ziemlich lange Zeichenfolge zu ändern, d. H. Die Anzahl der zu ändernden Zeichen ist groß.

0
Asif

Wenn Sie Wert auf Leistung legen, dann sollten Sie hier Allokationen vermeiden. Und wenn Sie auf .Net Core 2.1 oder höher (oder noch nicht veröffentlicht. .Net Standard 2.1) sind, können Sie mit der string.Create-Methode :

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

Diese Vorgehensweise ist schwieriger zu verstehen als die Alternativen, aber es ist die einzige, die nur ein Objekt pro Aufruf zuweist: die neu erstellte Zeichenfolge.

0
svick

Es ist besser, die String.substr() zu verwenden. 

So was:

ReplString = GivenStr.substr(0, PostostarRelStr)
           + GivenStr(PostostarRelStr, ReplString.lenght());
0
Varun_k