2010-02-18 4 views
7

У меня есть строка с 16 буквенно-цифровыми символами, например. F4194E7CC775F003. Я бы хотел отформатировать его как F419-4E7C-C775-F003.Форматирование буквенно-цифровой строки

Я попытался с помощью

string.Format("{0:####-####-####-####}","F4194E7CC775F003"); 

, но это не работает, так как это не числовое значение.

Так что я придумал следующее:

public class DashFormatter : IFormatProvider, ICustomFormatter 
{ 
    public object GetFormat(Type formatType) 
    { 
    return this; 
    } 

    public string Format(string format, object arg, IFormatProvider formatProvider) 
    { 
    char[] chars = arg.ToString().ToCharArray(); 
    StringBuilder sb = new StringBuilder(); 

    for (int i = 0; i < chars.Length; i++) 
    { 
     if (i > 0 && i % 4 == 0) 
     { 
     sb.Append('-'); 
     } 

     sb.Append(chars[i]); 
    } 

    return sb.ToString(); 
    } 
} 

и с помощью

string.Format(new DashFormatter(), "{0}", "F4194E7CC775F003"); 

Я был в состоянии решить эту проблему, но я надеялся, что есть лучший/простой способ сделать Это? Возможно, какая-то магия LINQ?

Спасибо.

+0

Я думал, что это было довольно просто, но, к сожалению, это не работает: 'string.Format (" {0} {1} {2} {3} - { 4} {5} {6} {7} - {8} {9} {10} {11} - {12} {13} {14} {15} ", aString.ToCharArray()); строка' – devuxer

+0

. Формат требует списка параметров. aString.ToCharArray() рассматривается как один параметр массива. – Carra

ответ

8

Вы можете сделать это в одной строке без Linq:

 StringBuilder splitMe = new StringBuilder("F4194E7CC775F003"); 
     string joined = splitMe.Insert(12, "-").Insert(8, "-").Insert(4, "-").ToString(); 
+0

+1 лучше, чем у меня, и лучше, чем у любого из решений LINQ –

+0

Добавил stringbuilder. – Carra

+0

Мне было интересно, какая из них была более эффективной, ваша или моя, поэтому я сделал быстрый тест - ваш в два раза быстрее ;-) –

0
char[] chars = "F4194E7CC775F003".ToCharArray(); 
      var str = string.Format("{0}-{1}-{2}-{3}" 
            , new string(chars.Take(4).ToArray()) 
            , new string(chars.Skip(4).Take(4).ToArray()) 
            , new string(chars.Skip(8).Take(4).ToArray()) 
            , new string(chars.Skip(12).Take(4).ToArray()) 
       ); 
+0

Очень уродливый, но LINQ действительно ;-) – Steven

+1

Прошу прощения, но это выглядит ужасно неэффективным, как алгоритм Шлемиеля Живописеля (http://www.joelonsoftware.com/articles/fog0000000319.html) – 2010-02-18 08:11:36

+0

loool, да, это уродливо :) –

1

Если вы хотите LINQ:

var formatted = string.Join("-", Enumerable.Range(0,4).Select(i=>s.Substring(i*4,4)).ToArray()); 

И если вы хотите эффективно:

var sb = new StringBuilder(19); 
sb.Append(s,0,4); 
for(var i = 1; i < 4; i++) 
{ 
sb.Append('-'); 
sb.Append(s,i*4, 4); 
} 
return sb.ToString(); 

Я не сравнивал этот, но я думаю, что это будет быстро er then StringBuilder.Insert, потому что он не перемещает остальную строку много раз, он просто пишет 4 символа. Также он не перераспределяет основную строку, потому что в начале она предварительно разделена на 19 символов.

+0

so damn coool :) –

+1

но я думаю, что ур отсутствует литье var s = string.Join ("-", Enumerable.Range (0, 4) .Выберите (i => "F4194E7CC775F003" .Substring (i * 4, 4)). ToArray()); –

+0

он может выглядеть как классный код, но он очень неэффективен. Я просто сделал некоторые тесты, и решение Carra в 3 раза быстрее –

0

решение Простейшее я могу думать о

 var text = "F4194E7CC775F003"; 
     var formattedText = string.Format(
      "{0}-{1}-{2}-{3}", 
      text.Substring(0, 4), 
      text.Substring(4, 4), 
      text.Substring(8, 4), 
      text.Substring(12, 4)); 
+0

, такое же, как TiTaN, менее уродливое;) – RvdK

+0

Решение Carra в два раза быстрее –

2

Вы можете сделать это с помощью регулярного выражения, хотя я не знаю, что производительность это будет по сравнению с другими методами.

string formattedString = Regex.Replace(yourString, "(\\S{4})\\B", "$1-"); 

Вы можете поместить это в метод расширения для строки тоже, если вы хотите сделать:

yourString.ToDashedFormat(); 
+0

извините, но это В 25 раз медленнее, чем решение Карры –

+0

Ой! Ну, я сказал, что не знал, какова будет производительность! –

1

на основе Carra's answer Я сделал этот небольшой служебный метод:

private static string ToDelimitedString(string input, int position, string delimiter) 
{ 
    StringBuilder sb = new StringBuilder(input); 

    int x = input.Length/position; 

    while (--x > 0) 
    { 
    sb = sb.Insert(x * position, delimiter); 
    } 

    return sb.ToString(); 
} 

You может использовать его следующим образом:

string result = ToDelimitedString("F4194E7CC775F003", 4, "-"); 

И тест:

[Test] 
public void ReturnsDelimitedString() 
{ 
    string input = "F4194E7CC775F003"; 

    string actual = ToDelimitedString(input, 4, "-"); 

    Assert.AreEqual("F419-4E7C-C775-F003", actual); 
}