2013-11-12 2 views
1

Я новичок в C#. У меня короткая форма и длинная форма клиентского кода. Краткая форма - это некоторые альфа-символы и некоторые числовые (ABC12), в то время как длинная форма всегда имеет длину 15 символов, а пространство между альфой и числовыми частями дополняется нулями (ABC000000000012). Мне нужно иметь возможность конвертировать из короткой формы в длинную. Ниже приведен следующий код: как мне это нужно - это лучший способ сделать это?Как вставить символы в буквенно-цифровую строку

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" 
} 
+4

Рабочие улучшения кода относятся на http://codereview.stackexchange.com –

+0

у не вы просто добавляете строку –

ответ

5

Ваш код в основном правильно, однако это может быть медленным, так как String.Substring(...) создает новую строку каждый раз, когда вызывается.

Я также предлагаю вам использовать встроенные функции .NET API для выполнения ваших задач, которые могут сделать кодирование проще много:

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)); 
} 
+0

Это замечательно - спасибо; Я знал, что это может быть более элегантно. Однако, когда я пробовал ваш подход, я получил ошибку - «Поле const ссылочного типа, кроме строки, может быть инициализировано только нулевым». Я обнаружил, что если я поместил список чисел непосредственно в функцию indexOfAny, он работал нормально. int index = s.IndexOfAny (новый символ char [] {'1', '2', '3', '4', '5', '6', '7', '8', '9', ' 0 '}); По какой причине я не должен этого делать? –

+0

Спасибо, я удалил «const». Нет никакой реальной причины, кроме того, что мне было легче читать ее. – Emiswelt

0

Вы можете использовать string.Format(), чтобы принять заботиться о прокладке для вас. Я использовал регулярное выражение (и не очень здраво) для анализа букв и цифр, но вы можете сделать это более эффективно другим способом.

Ключевым моментом является то, что мы динамически вычисляем, сколько нулей нам нужно, а затем используйте строку формата формы X:dY где X = порядковый номер формата и Y = количество нулей, которые вы хотите отложить.

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); 
+0

Этот вопрос имеет более компактный синтаксис заполнения: http://stackoverflow.com/questions/6842396/in-c-how-can-i-use-regex-replace-to-add-leading-zeroes-if-possible –

+0

Хорошее место, вероятно, было бы более эффективно делать это так. – gooid

1

Взгляните на это:

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(); 
} 

Я предполагаю, что строка всегда буква -> цифра (например, "abc123" или "ab1234").

1

чище, тем быстрее

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 для всех ответов заключается в следующем,

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; 
    } 
} 
+0

Извините, но этот подход очень медленный. Строки неизменны в C#, и поэтому + = создает новую строку каждый раз, что приводит к временной сложности O (n²) для вашего кода. (Это предполагает реализацию, подобную этой для C++, хотя) – Emiswelt

+1

Да, вы правы, я исправил ее, и теперь это в 4 раза быстрее вашего :) hihihi – mecek

+0

+1 для теста. Однако мне интересно узнать о версии версии Regex. – Emiswelt

Смежные вопросы