2009-04-07 11 views
5

C#, .NET 3.5Analisi di una stringa in C#; c'è un modo più pulito?

Questo mi sa solo di brutto, ma non riesco a pensare a un altro modo.

Dato una stringa con il formato di "Joe Smith (jsmith)" (senza virgolette), vorrei analizzare solo la stringa 'jsmith' all'interno della parentesi. Mi è venuta in mente questo:

private static string DecipherUserName(string user) 
{ 
    if(!user.Contains("(")) 
     return user; 

    int start = user.IndexOf("("); 

    return user.Substring(start).Replace("(", string.Empty).Replace(")", string.Empty); 
} 

Altro che la mia (dis) l'avversione sano per RegEx, c'è un modo più semplice per analizzare la stringa?

Edit: Per chiarire, la stringa da analizzare sarà sempre di: "Joe Smith (jsmith)" (sans virgolette).

risposta

9

Non dovrebbe essere necessario sostituire il primo dato che può solo aggiungere 1 in posizione "(".

private static string DecipherUserName (string user) {   
    int start = user.IndexOf("("); 
    if (start == -1) 
     return user; 
    return user.Substring (start+1).Replace(")", string.Empty); 
} 
+0

Nota: ho accettato il refactor di Pax sulla soluzione RegEx fornita come ritengo a lungo termine, questo sarà più mantenibile finché non diventerò più esperto in RegEx. Quello e un test rapido di 1000 nomi avevano la soluzione RegEx a .1165195 ms rispetto alla soluzione String a .0077423 ms. –

+0

Per una semplice corrispondenza del testo come questa, le RE sono di solito più lente (anche se possono essere compilate una volta per una maggiore velocità in un ciclo). Il loro vero vantaggio deriva dalla loro espressività per i casi più complessi (ad esempio, consentendo e rimuovendo gli spazi all'interno delle parentesi). Vale veramente la pena imparare, quindi continua così. – paxdiablo

2

Poiché la funzione IndexOf restituisce -1 quando il valore non esiste, si potrebbe fare le cose un po 'diverse ...

private static string DecipherUserName(string user) 
{   
    int start = user.IndexOf("("); 

    if (start > -1) 
    { 
     return user.Substring(start).Replace("(", string.Empty).Replace(")", string.Empty); 
    } 
    else 
    { 
     return user; 
    } 
} 
+0

Hai dimenticato che IndexOf restituirà -1 quando il valore non esiste. Grazie! –

20

regex sono così utili che ti risparmiare un sacco di mal di cuore mordere il proiettile e impararli. Non l'intero shebang, solo le basi.

Un'espressione regolare che funziona è "\ w + \ ((. *) \)" - jsmith si trova in Match.Groups [1].

Un modo semplice per raccogliere espressioni regolari è quello di trovare un sito web che ti consentono di digitare una regex e del testo poi sputare le partite ...

+0

+1 per espressioni regolari, poiché è lo strumento corretto –

+0

Non esiste un requisito esplicito che il nome utente racchiuso tra parentesi deve seguire un nome senza spazi. "\ (. * \)" dovrebbe essere sufficiente. – James

+0

Lo strumento giusto ma il RE sbagliato - ne hai bisogno uno che gestisca il caso di un utente senza parentesi. Fallo e ti darò un voto :-) – paxdiablo

5

una specie di hack ... ^^

return user.Substring(user.IndexOf('(') + 1).TrimEnd(')'); 

Se user non contiene parentesi aperta, IndexOf() restituisce -1, aggiungiamo uno, ottieni zero e SubString() restituisce l'intera stringa. TrimEnd() non avrà alcun effetto a meno che il nome dell'utente non termini con una parentesi chiusa.

Se user contiene una parentesi aperta, IndexOf() ritorna il suo indice, abbiamo Skipp la parentesi di apertura con l'aggiunta di uno, ed estrarre il resto della stringa con Substring(). Infine rimuoviamo la parentesi chiusa con TrimEnd().

+0

Uso piacevole della stringa API. –

+0

Questo non riflette tuttavia l'intenzione molto bene. –

+0

Prima riga: tipo di hack ... ^^;) –

1

userei

int start=user.IndexOf('('); 
if (start != -1) { 
    end = user.IndexOf(')', start); 
    return user.Substring(start+1,end-start-1); 
} else 
    return user; 

ma questo è solo un cambiamento cosmetico: l'utilizzo di caratteri in IndexOf è un po 'più veloce, e utilizzando il metodo Substring sembra esprimere più esattamente ciò che dovrebbe essere fatto (e la metodo è più robusto se si dispone di più coppie di parentesi ...)

detto questo, Daniel metodo L 's (utilizzando String.Split) potrebbe essere più semplice (ma non fare molto bene con le stringhe malformate e deve costruire un array di stringhe).

Tutto sommato, ti suggerisco di superare la tua avversione per le espressioni regolari, dal momento che quella situazione è esattamente ciò a cui sono destinate :-) ...

+0

@ Martin - Beh, è ​​un'avversione (non) salutare (-_ ^) Il tuo commento sulla sottostringa essendo più espressivo è sicuramente vero. –

5

Se la stringa utente è sempre nel formato "Joe Smith (jsmith)", questo dovrebbe funzionare.

E se la stringa utente è sempre "Joe Smith (jsmith)", funzionerà sempre.

private static string DecipherUserName(string user) 
{ 
    return "jsmith"; 
} 

La seconda voce solo a scopo di umorismo.

Problemi correlati