我有这个字符串:ABCDEFGHIJ
我需要使用字符串ZX
替换从第4个位置到第5个位置的字符串。
替换后的结果应该是:ABCZXFGHIJ
但不要使用 string.replace("DE","ZX")
这种方式,我需要使用位置来实现。
我该怎么做呢?
我有这个字符串:ABCDEFGHIJ
我需要使用字符串ZX
替换从第4个位置到第5个位置的字符串。
替换后的结果应该是:ABCZXFGHIJ
但不要使用 string.replace("DE","ZX")
这种方式,我需要使用位置来实现。
我该怎么做呢?
例如:表情符号''转换成字节后,相当于2个字符的大小。因此,如果Unicode字符位于字符串开头,
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) : ""
));
}
}
string myString = "ABCDEFGHIJ";
string modifiedString = new StringBuilder(myString){[3]='Z', [4]='X'}.ToString();
[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
}
}
}
我的解决方案利用了这个索引器的能力,直接改变内部维护的字符数组,我认为这是高效且简约的。
顺便说一句,我们可以更详细地重写上面的解决方案,例如:
string myString = "ABCDEFGHIJ";
StringBuilder tempString = new StringBuilder(myString);
tempString[3] = 'Z';
tempString[4] = 'X';
string modifiedString = tempString.ToString();
在这种情况下,我还想提到的是,在string
的情况下,它也有索引器属性来公开其内部字符数组,但在这种情况下,它只有Getter属性(没有Setter),因为字符串是不可变的。这就是为什么我们需要使用StringBuilder
来修改字符数组。
[IndexerName("Chars")]
public extern char this[int index] { [SecuritySafeCritical, __DynamicallyInvokable, MethodImpl(MethodImplOptions.InternalCall)] get; }
最后但并非最不重要的是,这个解决方案只适用于特定问题,其中要求仅在已知位置索引上替换少量字符。当需求是改变相对较长的字符串时,即需要改变的字符数量很多时,它可能不是最佳选择。
借助本文,我创建了以下带有额外长度检查的函数。
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");
}
}
我正在寻找一个具备以下要求的解决方案:
最适合我的解决方案是:
// 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 newString = oldStr.Substring(0, i) + c + oldString.Substring(i+1)
。默认情况下,如果没有指定长度,.Substring将提取字符串的其余部分。 - Sloan Reynolds你好,这段代码对我很有帮助:
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
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
我这样做
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
这是一个简单的扩展方法:
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();
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);
source[...start]
返回的是从索引0到start
(不包括start)的source
子字符串,source[end...]
也是类似的,只不过是从end
到字符串末尾。更多关于范围的信息在这里。public static class ForStrings
{
public static string ReplaceAt(this string source, int start, int end, string replacement)
{
return source[..start] + replacement + source[end..];
}
}
使用方法:
string OPsString = "ABCDEFGHIJ";
string newString = OPsString.ReplaceAt(3, 5, "ZX");
Console.WriteLine(newString); //"ABCZXFGHIJ"