2010-10-22 32 views
7

Así es como me gustaría escribir una función para hacer un acrónimo en estilo de Java:Obtener un acrónimo de una cadena en C# utilizando LINQ?

string makeAcronym(string str) 
    { 
     string result = ""; 
     for (int i = 0; i < str.Length; i++) 
     { 
      if (i == 0 && str[i].ToString() != " ") 
      { 
       result += str[i]; 
       continue; 
      } 

      if (str[i - 1].ToString() == " " && str[i].ToString() != " ") 
      { 
       result += str[i]; 
      } 
     } 

     return result; 
    } 

¿Existe una forma más elegante que puedo hacerlo con LINQ, o utilizando algún construido en función de C#?

Respuesta

13

Aquí hay un par de opciones

Un .NET 4 única opción usando string.join:

string acronym = string.Join(string.Empty, 
     input.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries).Select(s => s[0]) 
    ); 

En .NET 3.5 (o 4.0), se puede hacer:

string acronym = new string(input.Split(new[] {' '}, 
     stringSplitOptions.RemoveEmptyEntries).Select(s => s[0]).ToArray()); 

Otra opción (mi elección personal), basada en su lógica original:

string acronym = new string(
     input.Where((c,i) => c != ' ' && (i == 0 || input[i-1] == ' ')) 
     .ToArray() 
    ); 
+0

necesitarás .ToArray() allí después de tu Seleccionar. (A menos que .net4 ya no requiera esta conversión ... No sé) – spender

+0

@spender: No en .NET 4 (finalmente agregaron un join en IEnumerable) - solo en 3.5 ... http://msdn.microsoft .com/en-us/library/dd783876.aspx –

+0

parece una coma en el ejemplo 1, que aún no compilará para mí. –

0
string makeAcronym(string str) 
{ 
    return new string(str.Split(new [] {' '}, 
     StringSplitOptions.RemoveEmptyEntries).Select(s => s[0]).ToArray()); 
} 
+0

@Reed fixed. Malditos límites –

4

Usted puede hacer esto bastante bien utilizando una combinación de expresiones regulares/LINQ:

String 
    .Join("", 
     Regex 
      .Matches("this is a test",@"(?<=^|)\w") 
      .Cast<Match>() 
      .Select(m=>m.Value) 
      .ToArray() 
    ) 
+2

¿realmente necesita expresiones regulares? ¿Qué hay de 'Char.IsWhitespace'? –

+0

No, probablemente no necesite Regex, pero le da un mejor control sobre lo que representa el espacio en blanco entre las palabras. Si la lista llegara a incluir signos de puntuación (por ejemplo), Regex probablemente sería la mejor manera de resolver esto. Podría ser útil. – spender

2

LINQ puede trabajar para esto, pero en general, me parece que es mejor para construir string valores utilizando StringBuilder ejemplo. Esto le permite evitar asignaciones string innecesarias.

string makeAcronym(string str) { 
    var builder = new StringBuilder(); 
    for (var i = 0; i < str.Length; i++) { 
    var c = str[i]; 
    if (c == ' ') { 
     continue; 
    } 
    if (i == 0 || str[i-1] == ' ') { 
     builder.Append(c); 
    } 
    } 
    return builder.ToString(); 
} 
+0

@Reed, no necesariamente. Incluso consideré hacer de la parte interna del ciclo una consulta LINQ para devolver el 'char' para ponerlo en el generador (me puse vago y lo hice para la ruta). El único aspecto de rendimiento sobre esto que quise afirmar es que no asigna ninguna cadena intermedia. – JaredPar

+0

Me di cuenta de que después de volver a leer su comentario, que fue la razón por la que borré mi comentario;) Estoy de acuerdo, sin embargo, en que la eliminación de las cadenas intermedias es muy importante aquí. –

4

Puede usar el método LINQ Aggregate para hacerlo de una manera bastante elegante.

Algo como esto:

private static string MakeAcronym2(string str) 
{ 
    return str.Split(' ').Aggregate("", (x, y) => x += y[0]); 
} 
+0

Esto falla si alguna de las subcadenas está vacía. Y la agregación usando un StringBuilder sería más rápida. – CodesInChaos

+1

Desafío la noción de que StringBuilder sería sensiblemente más rápido en la práctica. – mtreit

+0

@CodeInChaos: Además, ¿puede dar un ejemplo de entrada que hará que esto falle?No estoy muy seguro de estar de acuerdo con tu frase de subcadena vacía. ¡Gracias! – mtreit

8

Aquí está una técnica que no he visto hasta ahora. Depende de la suposición de que todas las letras que deberían estar en el acrónimo (y solo esas letras) están en mayúsculas en la cadena.

string MakeAcronym(string input) 
{ 
    var chars = input.Where(Char.IsUpper).ToArray(); 
    return new String(chars); 
} 

// MakeAcronym("Transmission Control Protocol") == "TCP" 
Cuestiones relacionadas