首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用填充索引替换chars

用填充索引替换chars
EN

Stack Overflow用户
提问于 2021-07-30 08:19:34
回答 2查看 92关注 0票数 3

我有一个带有特殊字符的字符串,我必须用一个索引(左填充n '0‘)替换这些字符。

快速示例以获得更好的解释:

我有字符串“098000998383 $$$$”,索引(整数)3的结果应该是“098000998383 0003”。

这些特殊字符不一定是按顺序排列的。源字符串可能为空,也可能不包含任何特殊字符。

我已经写了一些有用的函数。

代码语言:javascript
复制
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;
    }
}

但我真的不喜欢它(首先,因为我把字符作为字符串传递..。而不是作为焦炭)。

代码语言:javascript
复制
string source = "000081059671####=1811";
int index = 5;
string character = "#";

string result = source.ReplaceCounter(index, character);

它能更加优化和紧凑吗?一些善良的灵魂能帮我吗?

提前感谢

编辑

索引是可变的,因此:

如果索引为15

代码语言:javascript
复制
string source = "000081059671####=1811";
int index = 15;
string character = "#";

string result = source.ReplaceCounter(index, character);
// result = "0000810596710015=1811"

这应该是检查我上面发布的代码中的索引> max号,如果发生这种情况,我会从索引中删除" max“值,直到索引

穆克斯号是什么?如果特殊字符数为4(如下面的示例所示),则最大值为9999。

代码语言:javascript
复制
string source = "000081059671####=1811";
// max number 9999
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-07-30 10:14:37

又一次编辑

从评论来看,似乎可以使用一个以上的数字。在这种情况下,可以将counter转换为string,并将其作为char[]来选择要在每次迭代中使用的字符:

代码语言:javascript
复制
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来修改字符串而不需要分配。在这种情况下,需要用一个字符替换最后一个匹配,用另一个字符替换所有其他匹配。这可以是一个简单的反向迭代:

代码语言:javascript
复制
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执行复杂的替换,而无需分配临时字符串。您可以使用替换重载之一,使用MatchEvaluator生成动态输出,而不仅仅是单个值。

在这种情况下:

代码语言:javascript
复制
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(字符串)转义字符来避免。

这可以用扩展方法打包。

代码语言:javascript
复制
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());

这段代码

代码语言:javascript
复制
var source= "0980 0099 8383 $$$$";
var result=source.ReplaceCounter(5,"$");

返回

代码语言:javascript
复制
0980 0099 8383 0003
票数 3
EN

Stack Overflow用户

发布于 2021-07-30 08:52:52

我建议这样的解决办法(摆脱帮助者的方法:

代码语言:javascript
复制
public static class StringExtensions
{
    public static string ReplaceCounter(this string source, int counter, char character)
    {
        string res = source;
        string strCounter = counter.ToString();
        bool counterTooLong = false;
        int idx;
        // Going from the and backwards, we fill with counter digits.
        for(int i = strCounter.Length - 1; i >= 0; i--)
        {
            idx = res.LastIndexOf(character);
            // if we run out of special characters, break the loop.
            if (idx == -1)
            {
                counterTooLong = true;
                break;
            }

            res = res.Remove(idx, 1).Insert(idx, strCounter[i].ToString());
        }
        // If we could not fit the counter, we simply throw exception
        if (counterTooLong) throw new InvalidOperationException();
        // If we did not fill all placeholders, we fill it with zeros.
        while (-1 != (idx = res.IndexOf(character))) res = res.Remove(idx, 1).Insert(idx, "0");

        return res;
    }
}

这是小提琴

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68587684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档