2010-02-18 11 views
7

Tengo una cadena con 16 caracteres alfanuméricos, p. F4194E7CC775F003. Me gustaría formatearlo como F419-4E7C-C775-F003.Formateo de cadena alfanumérica

He intentado utilizar

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

pero esto no funciona ya que no es un valor numérico.

Así que se le ocurrió la siguiente:

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

y mediante el uso

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

yo era capaz de resolver el problema, sin embargo yo estaba esperando que hay una manera mejor/más fácil de hacer ¿eso? Tal vez alguna magia LINQ?

Gracias.

+0

pensé que esto era bastante sencillo, pero, por desgracia, no funciona: 'string.Format (" {0} {1} {2} {3} - { 4} {5} {6} {7} - {8} {9} {10} {11} - {12} {13} {14} {15} ", aString.ToCharArray());' – devuxer

+0

cadena. formato requiere una lista de parámetros. aString.ToCharArray() se ve como un parámetro de matriz. – Carra

Respuesta

8

Puede hacerlo en una sola línea sin LINQ:

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

+1 mejor que el mío, y mejor que cualquiera de las soluciones LINQ –

+0

Stringbuilder añadido. – Carra

+0

Me preguntaba cuál era más eficiente, tu o la mía, así que hice un punto de referencia rápido: el tuyo es el doble de rápido ;-) –

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

Bastante feo, pero LINQ de hecho ;-) – Steven

+1

Lo siento, pero parece terriblemente ineficiente, como el algoritmo de Schlemiel the Painter (http://www.joelonsoftware.com/articles/fog0000000319.html) –

+0

loool, sí, es feo :) –

1

Si quieres que LINQ:

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

Y si lo desea eficiente:

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

No comparé este, pero creo que sería rápido entonces StringBuilder.Insert porque no mueve el resto de la cadena muchas veces, simplemente escribe 4 caracteres. Además, no reasignaría la cadena subyacente, porque está preasignada a 19 caracteres al principio.

+0

tan maldito coool :) –

+1

pero creo que falta el casting var s = string.Join ("-", Enumerable.Range (0, 4) .Seleccione (i => "F4194E7CC775F003" .Substring (i * 4, 4)). ToArray()); –

+0

puede parecer un código genial, pero es muy ineficiente. Acabo de hacer algunos puntos de referencia y la solución de Carra es 3 veces más rápida –

0

solución más simple que puedo pensar es

 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

igual que TiTaN, menos feo;) – RvdK

+0

La solución de Carra es dos veces más rápida –

2

que podría hacerlo con una expresión regular, aunque no sé lo que el rendimiento de esto estaría en comparación con los otros métodos.

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

Se puede poner esto en un método de extensión de cadena también, si usted quiere hacer:

yourString.ToDashedFormat(); 
+0

lo siento, pero esto es 25 veces más lento que la solución de Carra –

+0

¡Ay! Bueno, ¡dije que no sabía cómo sería la actuación! –

1

Basado en Carra's answer hice este pequeño método de utilidad:

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

Usted puede usarlo así:

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

Y un caso de prueba:

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

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

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