2009-04-07 6 views
5

C#, .NET 3.5Analyse d'une chaîne en C#; Y a-t-il une manière plus propre?

Cela me sent juste moche, mais je ne peux pas penser à une autre façon.

Étant donné une chaîne au format "Joe Smith (jsmith)" (sans guillemets), je voudrais analyser uniquement la chaîne "jsmith" entre parenthèses. Je suis venu avec ceci:

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

Autre que mon (non) saine aversion pour RegEx, est-il un moyen plus simple d'analyser le sous-chaîne?

Edit: Pour clarifier les choses, la chaîne à analyser sera toujours de: "Joe Smith (jsmith)" (sans guillemets).

Répondre

9

Vous ne devriez pas avoir le premier remplacer puisque vous pouvez simplement ajouter 1 à la "(position".

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

De note: j'ai accepté le refactor par Pax sur la solution RegEx fournie car je sens à long terme, ce sera plus maintenable jusqu'à ce que je devienne plus versé dans RegEx. Cela, et un test rapide de 1000 noms ont eu la solution RegEx à .1165195 ms vs. String solution à .0077423 ms. –

+0

Pour une simple correspondance de texte comme celle-ci, les RE sont généralement plus lents (bien qu'ils puissent être compilés une fois pour une vitesse supplémentaire dans une boucle). Leur véritable avantage vient de leur expressivité pour des cas plus complexes (par exemple, autoriser et supprimer des espaces à l'intérieur des parenthèses). Ça vaut vraiment la peine d'apprendre, alors continuez comme ça. – paxdiablo

2

Depuis la fonction IndexOf renvoie -1 lorsque la valeur n'existe pas, vous pouvez faire des choses un peu différentes ...

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

J'ai oublié que IndexOf retournera -1 lorsque la valeur n'existe pas. Merci! –

20

Regexes sont si utiles que vous vous sauverez une tonne de chagrin d'amour mordre la balle et les apprendre. Pas tout le shebang, juste les bases.

Une regex qui fonctionnera est "\ w + \ ((. *) \)" - jsmith serait dans Match.Groups [1].

Un moyen facile de ramasser regexes est de trouver un site qui va vous permettre de taper dans un regex et un texte puis cracher les allumettes ...

+0

+1 pour regex, puisque c'est le bon outil –

+0

Il n'y a aucune exigence explicite que le nom d'utilisateur paren-enclos doit suivre un nom sans espaces. "\ (. * \)" devrait suffire. – James

+0

Outil correct mais RE incorrect - vous en avez besoin d'un qui gérera le cas d'un utilisateur sans parenthèses. Faites-le et je vais vous donner un vote :-) – paxdiablo

5

Type d'un hack ... ^^

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

Si user ne contient pas entre parenthèses d'ouverture, IndexOf() renvoie -1, nous en ajoutons un, obtiens zéro, et SubString() renvoie la chaîne entière. TrimEnd() n'aura aucun effet à moins que le nom de l'utilisateur se termine par une parenthèse fermante.

Si user contient une parenthèse d'ouverture, IndexOf() retourne son index, nous Skipp la parenthèse d'ouverture en ajoutant un, et extraire le reste de la chaîne avec Substring(). Enfin, nous supprimons la parenthèse fermante avec TrimEnd().

+0

Joli usage de l'API chaîne. –

+0

Cela ne reflète pas très bien l'intention. –

+0

Première ligne: Genre de piratage ... ^^;) –

1

J'utilise

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

Mais c'est un simple changement cosmétique: en utilisant des caractères à IndexOf est un peu plus rapide, et en utilisant la méthode Substring semble exprimer plus exactement ce qu'il faut faire (et méthode est plus robuste si vous avez plusieurs paires de parenthèses ...)

Cela dit, méthode de Daniel L (en utilisant String.Split) pourrait être plus simple (mais ne traite pas très bien avec les chaînes malformées et doit construire un tableau de chaînes).

Dans l'ensemble, je vous suggère de surmonter votre aversion pour les expressions régulières, puisque cette situation est exactement ce à quoi elles sont destinées :-) ...

+0

@Martin - Eh bien, c'est une aversion (non) saine (-_ ^) Votre commentaire sur la sous-chaîne étant plus expressive est définitivement vrai. –

5

Si la chaîne utilisateur est toujours au format "Joe Smith (jsmith)", cela devrait fonctionner.

private static string DecipherUserName(string user) 
{ 
    string[] names = user.Split(new char[] {'(', ')'}); 
    return names.Length > 2 ? names[1] : user; 
} 

Et si la chaîne utilisateur est toujours "Joe Smith (jsmith)", cela fonctionnera toujours.

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

La deuxième entrée à des fins d'humour uniquement.

Questions connexes