简体   繁体   中英

How do I insert characters into an alpha-numeric string

I'm new to C#. I have a short form and a long form of a client code. The short form is some alpha characters and some numeric ones (ABC12), while the long form is always 15 characters long with the space between the alpha and the numeric parts padded out with zeros (ABC000000000012). I need to be able to convert from the short form to the long. The code below is how I've got it to work - is this the best way to do this?

public string ExpandCode(string s)
{
    // s = "ABC12"
    int i = 0;
    char c;
    bool foundDigit = false;
    string o = null;

    while (foundDigit == false)
    {
        c = Convert.ToChar(s.Substring(i, 1));
        if (Char.IsDigit(c))  
        {
            foundDigit = true;
            o = s.Substring(0, i) + new String('0', 15-s.Length) + s.Substring(i,s.Length-i); 
        }
        i += 1;
    }
    return (o); //o = "ABC000000000012"
}

Your code is basically correct, however it could be slow, since String.Substring(...) creates a new string every time called.

I also suggest that you use the built-in functions of the .NET api for accomplishing your tasks, which can make coding easier a lot:

private char[] numbers = new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};

public string ExpandCode(string s)
{
    //Find the first numeric char.
    int index = s.IndexOfAny(numbers);
    //Insert zeros and return the result. 
    return s.Insert(index, new String('0', 15 - s.Length));
}

Take a look at this:

public string ExpandCode(string s)
{
    var builder = new StringBuilder(s);
    var index = Array.FindIndex(s.ToArray(), x => char.IsDigit(x));

    while (builder.Length < 15)
    {
        builder.Insert(index, '0');
    }

    return builder.ToString();
}

I assume that string are always letter -> digit (like "abc123" or "ab1234").

The purer, the faster

public static string ExpandCode4(string s)
{
    char[] res = new char[15];
    int ind = 0;
    for (int i = 0; i < s.Length && s[i] >= 'A'; i++)
        res[ind++] = s[i];
    int tillDigit = ind;
    for (int i = 0; i < 15 - s.Length; i++)
        res[ind++] = '0';
    for (int i = 0; i < s.Length - tillDigit; i++)
        res[ind++] = s[tillDigit + i];
    return new string(res);
}

Benchmark for all the answers is as follows,

internal class Program
{
    private static void Main(string[] args)
    {
        var inputs = new List<string>();
        for (int i = 0; i < 10000000; i++)
        {
            inputs.Add("ABC1234");
        }

        var n1 = DateTime.Now;
        inputs.ForEach(i => ExpandCode1(i));
        var r1 = (DateTime.Now - n1).Ticks;

        var n2 = DateTime.Now;
        inputs.ForEach(i => ExpandCode2(i));
        var r2 = (DateTime.Now - n2).Ticks;

        var n3 = DateTime.Now;
        inputs.ForEach(i => ExpandCode3(i));
        var r3 = (DateTime.Now - n3).Ticks;

        var n4 = DateTime.Now;
        inputs.ForEach(i => ExpandCode4(i));
        var r4 = (DateTime.Now - n4).Ticks;

        var results = new List<Result>()
        {
            new Result() {Name = "1", Ticks = r1},
            new Result() {Name = "2", Ticks = r2},
            new Result() {Name = "3", Ticks = r3},
            new Result() {Name = "4", Ticks = r4}
        };
        results.OrderBy(r => r.Ticks).ToList().ForEach(Console.WriteLine);
        Console.ReadKey();
    }

    public static string ExpandCode4(string s)
    {
        char[] res = new char[15];
        int ind = 0;
        for (int i = 0; i < s.Length && s[i] >= 'A'; i++)
            res[ind++] = s[i];
        int tillDigit = ind;
        for (int i = 0; i < 15 - s.Length; i++)
            res[ind++] = '0';
        for (int i = 0; i < s.Length - tillDigit; i++)
            res[ind++] = s[tillDigit + i];
        return new string(res);
    }
    public static string ExpandCode1(string s)
    {
        char[] numbers = new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
        //Find the first numeric char.
        int index = s.IndexOfAny(numbers);
        //Insert zeros and return the result. 
        return s.Insert(index, new String('0', 15 - s.Length));
    }

    public static string ExpandCode2(string s)
    {
        var builder = new StringBuilder(s);
        var index = Array.FindIndex(s.ToArray(), x => char.IsDigit(x));

        while (builder.Length < 15)
        {
            builder.Insert(index, '0');
        }

        return builder.ToString();
    }

    public static string ExpandCode3(string s)
    {
        var match = Regex.Match(s, @"([^\d]+)(\d+)");
        var letters = match.Groups[1].Value;
        var numbers = int.Parse(match.Groups[2].Value);
        var formatString = "{0}{1:d" + (15 - letters.Length) + "}";
        var longForm = string.Format(formatString, letters, numbers);
        return longForm;
    }

}
public class Result
{
    public long Ticks { get; set; }
    public string Name { get; set; }
    public override string ToString()
    {
        return Name + " - " + Ticks;
    }
}

You can use string.Format() to take care of the padding for you. I used regex (and not in a very robust manner) to parse out the letters and numbers but you may be able to do this more efficiently another way.

The key point is that we dynamically figure out how many zero's we need, and then use a format string of the form X:dY where X = format ordinal and Y = the number of zeros you wish to pad.

var match = Regex.Match("ABC12", @"([^\d]+)(\d+)");
var letters = match.Groups[1].Value;
var numbers = int.Parse(match.Groups[2].Value);
var formatString = "{0}{1:d" + (15 - letters.Length) + "}";
var longForm = string.Format(formatString, letters, numbers);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM