[英]How to replace part of string by position?
我有这个字符串: ABCDEFGHIJ
我需要用字符串ZX
从位置 4 替换到位置 5
它看起来像这样: ABCZXFGHIJ
但不要与string.replace("DE","ZX")
一起使用 - 我需要与position一起使用
我该怎么做?
string s = "ABCDEFGH";
s= s.Remove(3, 2).Insert(3, "ZX");
在字符串中添加和删除范围的最简单方法是使用StringBuilder
。
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
另一种方法是使用String.Substring
,但我认为StringBuilder
代码变得更具可读性。
这是一个不使用 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);
}
使用此函数时,如果希望整个替换字符串替换尽可能多的字符,则将 length 设置为替换字符串的长度:
"0123456789".ReplaceAt(7, 5, "Hello") = "0123456Hello"
否则,您可以指定要删除的字符数:
"0123456789".ReplaceAt(2, 2, "Hello") = "01Hello456789"
如果将长度指定为 0,则此函数的作用类似于插入函数:
"0123456789".ReplaceAt(4, 0, "Hello") = "0123Hello456789"
我想这更有效,因为不需要初始化 StringBuilder 类并且因为它使用更多基本操作。 如果我错了,请纠正我。 :)
使用String.Substring()
(详见此处)切割左侧部分,然后是您的替换部分,然后是右侧部分。 玩索引,直到你做对了:)
就像是:
string replacement=original.Substring(0,start)+
rep+original.Substring(start+rep.Length);
如果您关心性能,那么您要避免的事情就是分配。 如果您使用的是 .Net Core 2.1+(或尚未发布的 .Net Standard 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));
});
}
这种方法比其他方法更难理解,但它是唯一一种每次调用只分配一个对象:新创建的字符串。
作为一种扩展方法。
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();
}
}
string s = "ABCDEFG";
string t = "st";
s = s.Remove(4, t.Length);
s = s.Insert(4, t);
就像其他人提到的那样, 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 次。所以它稍微慢了一点。
完后还有
public static string ReplaceAtPosition(this string self, int position, string newValue)
{
return self.Remove(position, newValue.Length).Insert(position, newValue);
}
你可以试试这个链接:
string str = "ABCDEFGHIJ";
str = str.Substring(0, 2) + "ZX" + str.Substring(5);
在这篇文章的帮助下,我创建了以下带有额外长度检查的函数
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");
}
}
如果字符串包含 Unicode 字符(如 Emojis),则所有其他答案都不起作用,因为 Unicode 字符比字符权重更多字节。
示例:表情符号 '🎶' 转换为字节,其权重相当于 2 个字符。 因此,如果将 unicode char 放在字符串的开头,则
offset
参数将被移动)。
有了这个主题,我将 StringInfo 类扩展为通过保持 Nick Miller 算法的位置来替换以避免这种情况:
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) : ""
));
}
}
我正在寻找具有以下要求的解决方案:
最适合我的解决方案是:
// replace `oldString[i]` with `c`
string newString = new StringBuilder(oldString).Replace(oldString[i], c, i, 1).ToString();
这使用StringBuilder.Replace(oldChar, newChar, position, count)
满足我要求的另一个解决方案是使用带有连接的Substring
:
string newString = oldStr.Substring(0, i) + c + oldString.Substring(i+1, oldString.Length);
这也可以。 我猜它的效率不如第一个性能明智(由于不必要的字符串连接)。 但过早的优化是万恶之源。
所以选择你最喜欢的一个:)
string myString = "ABCDEFGHIJ";
string modifiedString = new StringBuilder(myString){[3]='Z', [4]='X'}.ToString();
让我解释一下我的解决方案。
鉴于使用两个字符'Z'和'X'在其两个特定位置(“位置4到位置5”)更改字符串的问题陈述,并且要求使用位置索引来更改字符串而不是字符串替换( ) 方法(可能是因为实际字符串中某些字符可能重复),我宁愿使用极简方法来实现目标,而不是使用Substring()
和字符串Concat()
或字符串Remove()
和Insert()
方法。 尽管所有这些解决方案都将达到相同目标的目的,但这仅取决于个人选择和以极简主义方法解决的理念。
回到我上面提到的解决方案,如果我们仔细看看string
和StringBuilder
,它们都会在内部将给定的字符串视为字符数组。 如果我们看一下StringBuilder
的实现,它会维护一个内部变量,例如“ internal char[] m_ChunkChars;
” 来捕获给定的字符串。 现在由于这是一个内部变量,我们不能直接访问它。 对于外部世界,为了能够访问和更改该字符数组, StringBuilder
通过 indexer 属性公开它们,如下所示
[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
}
}
}
我上面提到的解决方案利用此索引器功能直接更改 IMO 高效且极简的内部维护的字符数组。
顺便提一句; 我们可以更详细地重写上述解决方案,如下所示
string myString = "ABCDEFGHIJ";
StringBuilder tempString = new StringBuilder(myString);
tempString[3] = 'Z';
tempString[4] = 'X';
string modifiedString = tempString.ToString();
在这种情况下还想提一下,在string
的情况下,它还具有 indexer 属性作为公开其内部字符数组的一种手段,但在这种情况下,它只有 Getter 属性(没有 Setter),因为字符串本质上是不可变的。 这就是为什么我们需要使用StringBuilder
来改变字符数组。
[IndexerName("Chars")]
public extern char this[int index] { [SecuritySafeCritical, __DynamicallyInvokable, MethodImpl(MethodImplOptions.InternalCall)] get; }
最后但并非最不重要的一点是,此解决方案仅最适合此特定问题,其中要求仅用已知位置索引替换少数字符。 当要求更改相当长的字符串(即要更改的字符数量很大)时,它可能不是最合适的。
最好使用String.substr()
。
像这样:
ReplString = GivenStr.substr(0, PostostarRelStr)
+ GivenStr(PostostarRelStr, ReplString.lenght());
String timestamp = "2019-09-18 21.42.05.000705";
String sub1 = timestamp.substring(0, 19).replace('.', ':');
String sub2 = timestamp.substring(19, timestamp.length());
System.out.println("Original String "+ timestamp);
System.out.println("Replaced Value "+ sub1+sub2);
这是一个简单的扩展方法:
public static class StringBuilderExtensions
{
public static StringBuilder Replace(this StringBuilder sb, int position, string newString)
=> sb.Replace(position, newString.Length, newString);
public static StringBuilder Replace(this StringBuilder sb, int position, int length, string newString)
=> (newString.Length <= length)
? sb.Remove(position, newString.Length).Insert(position, newString)
: sb.Remove(position, length).Insert(position, newString.Substring(0, length));
}
像这样使用它:
var theString = new string(' ', 10);
var sb = new StringBuilder(theString);
sb.Replace(5, "foo");
return sb.ToString();
我这样做
Dim QTT As Double
If IsDBNull(dr.Item(7)) Then
QTT = 0
Else
Dim value As String = dr.Item(7).ToString()
Dim posicpoint As Integer = value.LastIndexOf(".")
If posicpoint > 0 Then
Dim v As New Text.StringBuilder(value)
v.Remove(posicpoint, 1)
v.Insert(posicpoint, ",")
QTT = Convert.ToDouble(v.ToString())
Else
QTT = Convert.ToDouble(dr.Item(7).ToString())
End If
Console.WriteLine(QTT.ToString())
End If
假设我们知道要替换的字符串的索引。
string s = "ABCDEFGDEJ";
string z = "DE";
int i = s.IndexOf(z);
if(i == 3)
s = s.Remove(3,z.Length).Insert(3,"ZX");
//s = ABCZXFGDEJ
你好,这段代码对我有帮助:
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
我相信最简单的方法是这样的:(没有字符串生成器)
string myString = "ABCDEFGHIJ";
char[] replacementChars = {'Z', 'X'};
byte j = 0;
for (byte i = 3; i <= 4; i++, j++)
{
myString = myString.Replace(myString[i], replacementChars[j]);
}
这是有效的,因为字符串类型的变量可以被视为 char 变量的数组。 例如,您可以将名称为“myString”的字符串变量的第二个字符称为 myString[1]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.