我有一个带有特殊字符的字符串,我必须用一个索引替换这些字符(在左边填充 n '0')。
更好解释的快速示例:
我有字符串“0980 0099 8383 $$$$”和一个索引(整数)3 结果应该是“0980 0099 8383 0003”
特殊字符不一定按顺序排列。 源字符串可以为空或不包含任何特殊字符
我已经编写了可用的函数。
public static class StringExtensions
{
public static string ReplaceCounter(this string source, int counter, string character)
{
string res = source;
try
{
if (!string.IsNullOrEmpty(character))
{
if (res.Contains(character))
{
// Get ALL Indexes position of character
var Indexes = GetIndexes(res, character);
int max = GetMaxValue(Indexes.Count);
while (counter >= max)
{
counter -= max;
}
var new_value = counter.ToString().PadLeft(Indexes.Count, '0');
for (int i = 0; i < Indexes.Count; i++)
{
res = res.Remove(Indexes[i], 1).Insert(Indexes[i], new_value[i].ToString());
}
}
}
}
catch (Exception)
{
res = source;
}
return res;
}
private static List<int> GetIndexes(string mainString, string toFind)
{
var Indexes = new List<int>();
for (int i = mainString.IndexOf(toFind); i > -1; i = mainString.IndexOf(toFind, i + 1))
{
// for loop end when i=-1 (line.counter not found)
Indexes.Add(i);
}
return Indexes;
}
private static int GetMaxValue(int numIndexes)
{
int max = 0;
for (int i = 0; i < numIndexes; i++)
{
if (i == 0)
max = 9;
else
max = max * 10 + 9;
}
return max;
}
}
但我不太喜欢它(首先是因为我将 char 作为字符串传递......而不是作为 char)。
string source = "000081059671####=1811";
int index = 5;
string character = "#";
string result = source.ReplaceCounter(index, character);
能不能更优化更紧凑? 有好心人可以帮助我吗?
提前致谢
编辑
索引是可变的,所以:
如果索引为15
string source = "000081059671####=1811";
int index = 15;
string character = "#";
string result = source.ReplaceCounter(index, character);
// result = "0000810596710015=1811"
应该检查索引是否 > 最大数量 在我上面发布的代码中,如果发生这种情况,我会从索引中删除“最大”值,直到索引 < 最大数
什么是复数?如果特殊字符数为 4(如下例所示),最大数将为 9999
string source = "000081059671####=1811";
// max number 9999
最佳答案
又一次修改
从评论看来,可以使用不止一个数字。在这种情况下,counter
可以转换为 string
并作为 char[]
来选择在每次迭代中使用的字符:
public static string ReplaceCounter(this string source,
int counter,
char character)
{
var sb=new StringBuilder(source);
var replacements=counter.ToString();
int r=replacements.Length-1;
for(int i=sb.Length-1;i>=0;i--)
{
if(sb[i]==character)
{
sb[i]=r>=0 ? replacements[r--] : '0';
}
}
return sb.ToString();
}
这可以用于任意数量的数字。"0980 0099 8383 $$$$".ReplaceCounter(15,'$')
生成 0980 0099 8383 0015
编辑
发布原始答案后,我记得可以使用 StringBuilder
修改字符串而不进行分配。在这种情况下,最后一个匹配项需要替换为一个字符,所有其他匹配项替换为另一个字符。这可以是一个简单的反向迭代:
public static string ReplaceCounter(this string source,
int counter,
char character)
{
var sb=new StringBuilder(source);
bool useChar=true;
for(int i=sb.Length-1;i>=0;i--)
{
if(sb[i]==character)
{
sb[i]=useChar?(char)('0'+counter):'0';
useChar=false;
}
}
return sb.ToString();
}
Console.WriteLine("0000##81#059671####=1811".ReplaceCounter(5,'#'));
Console.WriteLine("0980 0099 8383 $$$$".ReplaceCounter(3,'$'));
------
0000008100596710005=1811
0980 0099 8383 0003
原始答案
任何字符串修改操作都会产生一个新的临时字符串,需要对其进行垃圾回收。这加起来如此之快,以至于在处理大量文本或大量请求时,避免使用临时字符串可以使速度提高 10 倍以上。这比使用并行处理要好。
您可以使用 Regex.Replace在不分配临时字符串的情况下执行复杂的替换。您可以使用 Replace 之一使用 MatchEvaluator
产生动态输出的重载,而不仅仅是单个值。
在这种情况下:
var source = "0000##81#059671####=1811";
var result = Regex.Replace(source,"#", m=>m.NextMatch().Success?"0":"5");
Console.WriteLine(result);
--------
0000008100596710005=1811
Match.NextMatch()返回源中的下一个匹配项,因此 m.NextMatch().Success
可用于识别最后一个匹配项并将其替换为 index
。
如果字符是 Regex 模式字符之一,这将失败。这可以通过使用 Regex.Escape(string) 转义字符来避免。
这可以用扩展方法打包
public static string ReplaceCounter(this string source,
int counter,
string character)
{
return Regex.Replace(source,
Regex.Escape(character),
m=>m.NextMatch().Success?"0":counter.ToString());
}
public static string ReplaceCounter(this string source,
int counter,
char character)
=>ReplaceCounter(source,counter,character.ToString());
这段代码
var source= "0980 0099 8383 $$$$";
var result=source.ReplaceCounter(5,"$");
返回
0980 0099 8383 0003
关于c# - 用填充索引替换字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68587684/