c# - 用填充索引替换字符

标签 c# string algorithm

我有一个带有特殊字符的字符串,我必须用一个索引替换这些字符(在左边填充 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/

相关文章:

algorithm - 最短路径算法 : multiple source, 最近目的地

c# - 为什么我的 PHP SHA256 哈希不等同于 C# SHA256Managed 哈希

c# - 本地序列不能用于查询运算符的 LINQ to SQL 实现,但 Contains() 运算符除外

c# - ASP.NET MVC3 在 View 中使用模型和自定义 ValidationModel

c - 访问地址位于 C 字符串中的指针

c - 使用 scanf 将字符串存储到字符串数组中

c++ - 到达指定时间间隔的整数流需要看起来已排序

c# - Linq Include 和 Where 父子关系条件

Python 在多行字符串中替换

python - 范围的整数列表