如何通过位置替换字符串的一部分?

213

我有这个字符串:ABCDEFGHIJ

我需要使用字符串ZX替换从第4个位置到第5个位置的字符串。

替换后的结果应该是:ABCZXFGHIJ

但不要使用 string.replace("DE","ZX") 这种方式,我需要使用位置来实现。

我该怎么做呢?


@TotZam - 请检查日期。这个比你链接的那个旧。 - ToolmakerSteve
@ToolmakerSteve 我通常会关注问题和答案的质量,而不是日期,就像这里所说的那样。在这种情况下,我似乎犯了一个错误,点击了错误的重复标记,因为这个问题的质量显然更好,所以我已经标记了另一个问题。 - Tot Zam
@TotZam - 啊,我不知道那个建议 - 谢谢你指出来。尽管看到一些旧的问题被报告为新的重复问题很令人困惑,所以在这种情况下,值得明确解释你正在标记一个更旧的问题为重复,因为链接的问题有更好的答案。 - ToolmakerSteve
22个回答

285
string s = "ABCDEFGH";
s= s.Remove(3, 2).Insert(3, "ZX");

25
我更喜欢这种方法,而不是初始化一个新的 StringBuilder(...)。谢谢! - Michael Norgren
5
我不知道为什么有人会在这个操作中使用StringBuilder。这是一个好回答。 - NappingRabbit

232

在字符串中添加和删除范围的最简单方法是使用StringBuilder

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

另一种选择是使用String.Substring,但我认为StringBuilder代码更易读。


6
最好用扩展方法来封装它 :) - balexandre
2
你为什么在这里使用StringBuilder?看看V4Vendetta的答案,那个更易读一些... - Fortega
3
Remove() 和 Insert() 每次操作都会创建并返回一个新的字符串。使用 StringBuilder 的方法则通过在预先分配的内存区域中操作字符来避免这种额外的开销。 - redcalx
@redcalx 这是真的,但是引入一个StringBuilder对象会增加额外的成本,并降低可读性。 - Fortega
4
如果你像V4Vendetta一样直接在字符串上使用Remove和Insert,那么在这里使用StringBuilder有何意义呢?看起来代码是多余的。 - HamsterWithPitchfork
请勿争论。如果您只进行一两个替换,那么可能并不重要,您可以选择最喜欢的变体。但是,如果您进行了大量替换,则可能需要使用Benchmark.NET来确定哪种方法最适合您的用例。 - MovGP0

56

ReplaceAt(int index, int length, string replace)

这是一个扩展方法,它不使用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 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);
}

当使用此函数时,如果您希望整个替换字符串尽可能地替换多个字符,请将长度设置为替换字符串的长度:

"0123456789".ReplaceAt(7, 5, "Hello") = "0123456Hello"
否则,您可以指定要删除的字符数:
"0123456789".ReplaceAt(2, 2, "Hello") = "01Hello456789"
如果您将长度指定为0,则此函数的行为就像插入函数一样。
"0123456789".ReplaceAt(4, 0, "Hello") = "0123Hello456789"

我猜这样更有效率,因为StringBuilder类无需初始化,并且使用了更基本的操作。如果我错了,请纠正我。:)


5
如果字符串长度超过200个字符,Stringbuilder会更高效。 - Tim Schmelter
没有压力。直接完成了。谢谢。 - D_Edet

14

如果你关心性能,那么你要避免的就是分配内存。如果你在 .Net Core 2.1+ 上,可以使用 string.Create 方法

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

虽然这种方法比其他方法更难理解,但它是唯一一个每次调用仅分配一个对象的方法:新创建的字符串。


10

使用String.Substring()(详情请看这里)来截取左部分,然后是你的替换内容,再加上右部分。通过调整索引直到得到正确结果 :)

类似于以下方式:

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

3
我使用上述三种方法创造了三个方法(string.Remove/Insert、Stringbuilder.Remove/Insert和Daniel的Substring答案),其中SubString是最快的方法。 - Francine DeGrood Taylor

8
        string s = "ABCDEFG";
        string t = "st";
        s = s.Remove(4, t.Length);
        s = s.Insert(4, t);

这个有效,你可能不想再把t放回去了。 - Pierre

8
作为扩展方法。
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();
    }
}

4
您可以尝试像这样的内容:

您可以尝试类似于以下内容:

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

4

Yet another

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

4

正如其他人所提到的,Substring()函数是有其存在的原因:

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

我还将其与StringBuilder解决方案进行了时间比较,结果是900个滴答声对875个滴答声。因此它略微慢一些。


@Aaron.S - 不是的。在我的例子中,"ABCDEFGHIJ"和"ZX"的长度是不同的。 - John Alexiou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接