12
votes

Diviser une chaîne de Pascalcase en mots distincts

Je cherche un moyen de scinder les chaînes Pascalcase, par exemple "Mystring", dans des mots séparés - "My", "String". Un autre utilisateur pose la question pour bash , mais Je veux savoir comment faire avec des expressions générales régulières ou du moins à .NET.

Bonus Si vous pouvez trouver un moyen de diviser également (et éventuellement capitaliser) Camelcase Strings: E.G. "mystring" devient "ma" et "chaîne", avec la possibilité de capitaliser / en minuscule soit ou des deux cordes.


3 commentaires

Dupliqué possible de Y a-t-il un moyen élégant d'analyser un mot et d'ajouter des espaces avant les lettres majuscules


Cette question est spécifique à .NET, mais les réponses de regex pourraient être appliquées ailleurs.


Découvrez la question Dupe: La réponse acceptée a la regex à scinder anxmlandxslt2.0tool à [an] [xml] [et] [xslt] [2.0] [outil] . Il utilise des recherches sur les regards que l'on peut discuter est assez lisible.


10 Réponses :


1
votes
Camel
Case
Word

5 commentaires

1) Compilez la Regexp pour une certaine vitesse. 2) Ce sera toujours plus lent que de le faire à la main.


@Steven, je conviens que cela devrait être compilé à la vitesse, mais c'est la fonctionnalité que je vais après pour le moment. Que voulez-vous dire que ce sera "plus lent que le faire à la main"? Si je me réfléchis à un objet avec un tas de propriétés publiques et convertissez les noms de Pascalcase en mots séparés, ce sera beaucoup plus rapide (temps de développement et de maintenance) le faisant de manière programmatique que à la main.


Je n'ai pas vu la vitesse mentionnée comme une exigence. De plus, je pense que "le faire à la main" fait référence à la rédaction de votre propre code d'analyse de chaîne qui peut être plus rapide mais sera significativement plus de code et plus de test.


@Ken Cette méthode ne gère pas Camelcase, de sorte que le "A" a été abandonné (voir Modifier à la réponse).


@Pat: Qu'est-ce que Ron a dit correctement: "à la main" signifie écrire votre propre code pour boucler sur la chaîne, le caractère par caractère, construisant chaque mot dans un StringBuilder et émettre au besoin.



0
votes

Vérifiez qu'un caractère non-Word vient au début de votre regex avec \ w code> et conserver les chaînes individuelles ensemble, puis divisez les mots.

Quelque chose comme: \ w ([AZ] [A-ZA-Z] +) + CODE> P>

pour: SDCSDS SD ACAMELCASEWORD COMMZ DASD que ASSDCACDCDC Pascelcase DFSADSSDD SD CODE> Sorties: P>

48: PascelCase
59: DfsadSsdd


2 commentaires

Hmmm. Cela ne fonctionne pas tout droit pour la regex de .NET, mais peut-être avec une petite documentation creuser ...


Vous devez utiliser \ b (limite de mot) pour correspondre au début du mot, pas \ w .



0
votes

dans RUBY:

"aCamelCaseWord".split /(?=[[:upper:]])/
=> ["a", "Camel", "Case", "Word"]


3 commentaires

C'est un lookahead positif, n'est-ce pas? Je ne peux pas obtenir un équivalent de travailler pour .NET, même lorsque je remplace [[[: supérieure:]] avec [AZ] ( en.wikipedia.org/wiki/regular_expression ).


.NET REGEX ne prend pas en charge la syntaxe de la classe de caractères POSIX. Vous pouvez utiliser \ p {lu} à la place, mais [A-Z] suffira probablement. Quoi qu'il en soit, cette approche est trop simpliste. Découvrez l'autre question, notamment le Split Regex @Poly est venu avec. C'est vraiment ce compliqué.


@PAT: Cet article Wikipedia n'est pas destiné à être utilisé comme référence; Trop général et trop théorique. Ce site est beaucoup plus utile: régulier-expressions.info



6
votes

répondit dans une question différente : xxx

sorties un mot de boîtier de chameau ( .Dump () est juste imprime sur la console). >


4 commentaires

Qu'est-ce qui doit arriver pour les chaînes comme ceci: acamelcasexml ? Lecture de la question, je m'attendrais à ce que un cas de chameau XML . Au lieu de cela, il donne un boîtier de chameau x m l .


@Mainma c'est vrai. Suivant les normes de nommage .NET, tous les acronymes trois lettres ou plus (par exemple XML) seraient en bonne cas (c'est-à-dire des acronymes de deux lettres (par exemple IP pour iPaddress), entraîneraient toujours un problème. Il serait préférable d'avoir l'algorithme gérer cette affaire.


Y a-t-il une fonction de sortie qui fait cela?


Je suggérerais: nouvelle regex (@ "(? <= [Az]) (? = [AZ] [AZ] [AZ]) | (? <= [^ Az]) (? = [AZ]) | ( ? <= [A-ZA-Z]) (? = [^ A-ZA-Z]) ", Regexoption.ignorePatternwhwitpace comme Stackoverflow.com/Questtions/3103730/... dit



18
votes

Voir cette question: Y a-t-il un moyen élégant d'analyser un mot et d'ajouter des espaces avant les lettres majuscules? Sa réponse acceptée couvre ce que vous voulez, y compris des chiffres et plusieurs lettres majuscules d'affilée. Bien que cet échantillon ait des mots commençant en majuscule, il est également valide lorsque le premier mot est en minuscule.

[Automatic][Tracking][System]
[XML][Editor]
[An][XML][And][XSLT][2.0][Tool]


7 commentaires

@Steven Sudit: Oui. Regex est l'un des meilleurs outils de ce type de problème. L'autre question vient d'être roulée avec un ensemble plus important de cas d'utilisation des échantillons.


@chilltemp, connaissez-vous une fonction intégrée pour cela?


@Shimmy: Non. Je vous recommande d'utiliser les informations dans la question liée pour créer une bibliothèque réutilisable.


J'ai fait ma propre fonction qui n'utilise pas Regex.


@chilltemp, je pense que cela coûte moins de performance. Si je me trompe, corrigez-moi et je vais utiliser la manière de Regex.


@Shimmy: La performance varie considérablement en fonction de nombreux facteurs, notamment la complexité de la regex et si elle est compilée. Tout comme la performance de C # varie en fonction de la façon dont vous l'utilisez. Cela étant dit, j'ai toujours trouvé Regex à .net pour être assez rapide pour mes besoins (système transactionnel en temps réel avec un haut débit). Les seuls moyens de réellement se comparer consiste à regarder l'IL et / ou les essais programmés générés.


D'accord. Je suis allé à votre fonction. BTW, j'ai édité votre réponse afin que les utilisateurs n'ont pas à dire "alors?".



4
votes

Que diriez-vous:

static IEnumerable<string> SplitPascalCase(this string text)
{
    var sb = new StringBuilder();
    using (var reader = new StringReader(text))
    {
        while (reader.Peek() != -1)
        {
            char c = (char)reader.Read();
            if (char.IsUpper(c) && sb.Length > 0)
            {
                yield return sb.ToString();
                sb.Length = 0;
            }

            sb.Append(c);
        }
    }

    if (sb.Length > 0)
        yield return sb.ToString();
}


3 commentaires

Ce serait une solution "à la main".


@Steven Sudit: Ouais ... était-ce interdit ou quelque chose comme ça?


Non, non, pas du tout. Il y avait juste une certaine confusion quant à ce que "à la main" signifiait, quand j'ai suggéré que de taper comme une alternative à la réégalité. En fait, je pense que Regexp, pour tout son pouvoir, est surutilisé. Pour de nombreux emplois, c'est un mauvais ajustement, conduisant à un code cryptique et à une mauvaise performance.



10
votes

Juste pour fournir une alternative aux solutions REGEX et de boucle Toutes les prêts fournis ici sont une réponse à l'aide de LINQ, qui gère également un boîtier de chameau et des acronymes: xxx

la sortie de ceci est: xxx


2 commentaires

C'est mon préféré absolu :)


Il convient de noter que cela ne fonctionne pas pour les acronymes mélangés à d'autres mots, si l'attente est de traiter l'acronyme comme son propre mot. Par exemple, httpresponeeexception convertit sur httpresponse exception .



3
votes

avec les objectifs de

  • a) Création d'une fonction qui optimise les performances
  • b) ont mon propre prise sur Camelcase dans laquelle des acronymes capitalisés n'ont pas été séparés (j'accepte parfaitement que ce n'est pas la définition standard de l'affaire Camel ou Pascal, mais ce n'est pas une utilisation rare): "TesttlaContainingCamelcase" devient "test TLA Contenant un boîtier de chameau "(TLA = trois lettres acronyme)

    J'ai donc créé la fonction suivante (non regex, verbeuse, mais orientée vers la performance) xxx

    Quoi de plus surprenant était les tests de performance. en utilisant 1 000 000 itérations par fonction xxx

    La méthode de l'instance de regex n'était que légèrement plus rapide que la méthode statique, même plus d'un million d'itérations (et je ne peux pas voir l'avantage de Utilisation du drapeau Regexoptions.Compiled) et le code très succinct de Dan Tao était presque aussi rapide que mon code beaucoup moins clair!


0 commentaires

0
votes
    public static string PascalCaseToSentence(string input)
    {
        if (input == null) return "";

        string output = Regex.Replace(input, @"(?<=[A-Z])(?=[A-Z][a-z])|(?<=[^A-Z])(?=[A-Z])|(?<=[A-Za-z])(?=[^A-Za-z])", m => " " + m.Value);
        return output;
    }
Based on Shimmy's answer.

0 commentaires

1
votes
string.Concat(str.Select(x => Char.IsUpper(x) ? " " + x : x.ToString())).TrimStart(' ').Dump();
This is far better approach then using Regex, Dump is just to print to console

0 commentaires