2010-10-22 21 views
7

Ecco come avrei scritto una funzione per fare un acronimo in stile Java:Ottieni un acronimo da una stringa in C# usando 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; 
    } 

C'è un modo più elegante che posso farlo con LINQ, o utilizzando qualche costruito in funzione di C#?

risposta

13

Qui ci sono un paio di opzioni

Un .NET 4 unica opzione utilizzando string.join:

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

In .NET 3.5 (o 4.0), si può fare:

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

Un'altra opzione (la mia scelta personale), basata sulla logica originale:

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

ti serviranno .ToArray() lì dopo il tuo Select. (A meno che .net4 non richieda più questa conversione ... Non lo so) – spender

+0

@spender: Non in .NET 4 (hanno infine aggiunto un join su IEnumerable) - solo in 3.5 ... http://msdn.microsoft .com/it/us/library/dd783876.aspx –

+0

sembra una virgola vagante nell'esempio 1, che comunque non verrà compilata per me. –

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

@Reed corretto. I dannati limiti –

4

È possibile farlo abbastanza bene usando una combinazione Regex/Linq:

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

hai davvero bisogno di regex? Che dire di 'Char.IsWhitespace'? –

+0

No, probabilmente non hai bisogno di Regex, ma ti dà un controllo migliore su ciò che rappresenta lo spazio bianco tra le parole. Se la lista dovesse includere la punteggiatura (ad esempio), Regex sarebbe probabilmente il mezzo più tosto per risolvere questo problema. Potrebbe essere utile. – spender

2

LINQ può lavorare per questo, ma in generale trovo che sia meglio costruire string valori utilizzando StringBuilder esempio. Ciò consente di evitare allocazioni string non necessarie.

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, non necessariamente. Ho anche considerato di rendere la parte interna del ciclo una query LINQ per restituire il 'char' da inserire nel builder (sono appena diventato pigro e l'ho fatto per il percorso). L'unico aspetto delle prestazioni su questo che intendevo affermare è che non alloca stringhe intermedie. – JaredPar

+0

Ho capito che dopo aver riletto il tuo commento, ecco perché ho cancellato il mio commento;) Sono d'accordo, però, che eliminare le stringhe intermedie è molto importante qui. –

4

È possibile utilizzare il metodo LINQ Aggregate per farlo in modo abbastanza elegante.

Qualcosa di simile a questo:

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

Questo fallisce se una delle sottostringhe è vuota. E l'aggregazione usando un StringBuilder sarebbe più veloce. – CodesInChaos

+1

Sfido l'idea che StringBuilder sarebbe percettibilmente più veloce nella pratica. – mtreit

+0

@CodeInChaos: Inoltre, puoi dare un esempio di input che causerà il fallimento di questo?Non sono abbastanza sicuro di essere d'accordo con la tua dichiarazione di sottostringa vuota. Grazie! – mtreit

8

Ecco una tecnica che non ho visto finora. Dipende dal presupposto che tutte le lettere che dovrebbero essere nell'acronimo (e solo quelle lettere) siano in maiuscolo nella stringa.

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

// MakeAcronym("Transmission Control Protocol") == "TCP" 
Problemi correlati