1
votes

RegEx pour faire correspondre «01,0 à 60,0 par pas de 0,5 ou 99,9»?

Je crée une API pour communiquer avec un aspirateur industriel.

Les valeurs de fréquence moteur valides sont comme indiqué ci-dessous, sous la forme XX.X:

01.0 à 60.0 par étapes de 0,5 Hz, ou 99,9 Hz

Je suis moi-même arrivé à la solution suivante (en python):

import re
p = re.compile('[0-5]\d.[05]|01.0|60.0|99.9')

Cependant, je peux toujours correspondre à 00,5, ce qui ne doit pas correspondre.

Je ne veux pas exclure explicitement 00.5, et peut-être ai-je oublié un autre cas final que je n'ai pas vérifié.

Comment résoudre ce problème ?


4 commentaires

Même si la solution de Joseph Bailey fonctionne, je pense toujours qu'il serait préférable de s'en tenir aux types flottants pour de telles comparaisons (en supposant que la fréquence du moteur est également un flottant)


J'adorerais que vous partagiez votre idée sur la façon de vérifier la validité de ces données à l'aide de types flottants. Je suis passé à str parce que le meilleur moyen me semblait par regex au lieu de plusieurs déclarations de condition.


Eh bien, vous devez définir le format de l'entrée pour être honnête.


En fait, j'ai écrit ci-dessus et j'ai pensé qu'il était clair que le formatage d'entrée devrait être: XX.X (X étant n'importe quel caractère Unicode). Je code en python, donc le type de variable n'est pas exactement défini.


4 Réponses :


1
votes

Ajoutez simplement 0 [1-9] \. [05] comme option et limitez l'autre base à 1-5

p = re.compile('0[1-9]\.[05]|[1-5]\d\.[05]|60\.0|99\.9')

Vous devez également utilisez \. au lieu de . car . signifie n'importe quel caractère. Enfin plus besoin de la condition 01.0


5 commentaires

Merci! Ça a l'air si simple et incroyable.


Je pense que vous devriez ajouter ^ et $ sinon cela pourrait également correspondre à "abc55.5xyz"


Yeh il devrait, dépend vraiment de ce que l'entrée est bien sûr, peut-être que c'est 01.0hz? Je ne sais pas pourquoi il a besoin de l'expression régulière, mais comme il s'agit davantage d'une question d'expression régulière, je le laisserai pour l'ajuster.


Je la voulais comme regex en raison de la complexité du problème, et en ce qui concerne le processeur, je pense que cette méthode est plus rapide que les opérations mathématiques et que plusieurs instructions `` si '' permettent de tester la validité des types `` float '' sous la forme requise.


OK alors veuillez accepter si c'est ce que vous recherchez.



1
votes

Le \ d correspond aux chiffres 0-9. Si vous ne voulez pas que la valeur commence par 00 , vous pouvez utiliser une anticipation négative (?! 00)

Vous pouvez utiliser:

^(?!00)[0-5]\d\.[05]|60\.0|99\.9$
  • ^ (?! 00) Début de chaîne et affirmer que ce qui est directement à droite n'est pas 00
  • [0-5] \ d Correspondance 00 - 59
  • \. [05] | 60 \ .0 | 99 \ .9 Faire correspondre un point et un chiffre 0 ou 5 ou 60,0 ou 99,9
  • $ Fin de chaîne
  • Démo Regex


    1 commentaires

    cela ne correspondra pas à 10, 20, 30, 40 ou 50



    0
    votes

    Étant donné que les données enregistrées par des appareils de mesure ou par toutes sortes d'appareils industriels sont généralement de type float , je recommande fortement de conserver le type float et d'éviter la conversion en chaîne. Ceci présente l'avantage d'éviter les chaînes correspondantes comme '"abc55.5xyz"' et seuls les flottants valides sont enregistrés. Cela devrait également être plus rapide que l'utilisation de regex avec une conversion float-> str. Vous pouvez par exemple utiliser numpy pour vérifier les valeurs correctes.

    Vous devez d'abord créer un tableau de valeurs correctes. Vous ne devez le faire qu'une seule fois au début de votre code. Pas besoin de le faire à chaque itération.

    motor_freq in correct_vals
    

    Vous pouvez maintenant vérifier les valeurs correctes avec

    import numpy as np
    lowest_val = 1.
    interm_val = 60.
    stepsize = .5
    highest_val = 99.9
    # create the array of correct values:
    correct_vals = np.empty(120)
    # fill array with steps:
    correct_vals[:-1] = np.linspace(lowest_val, interm_val, num=int((interm_val - lowest_val)/stepsize + 1))
    correct_vals[-1] = highest_val  # add highest value
    

    Cela retournera True lorsque la fréquence du moteur est comprise dans les valeurs spécifiées, sinon False . Si, comme vous l'avez ajouté, vos données sont constituées de caractères unicode de format XX.X , vous devrez les convertir en float pour la comparaison, par exemple avec motor_freq = float ('15 .5 ')


    3 commentaires

    Merci, cependant, les données sont envoyées par communication série au format ASCII de toute façon, octet par octet, donc le formatage en flottant, puis l'analyse ou le formatage sous forme d'octet semble être épuisant, au lieu d'une seule ligne avec regex.


    Ah d'accord. Ouais, alors il vaut peut-être mieux utiliser regex. Cependant, si vous souhaitez stocker / traiter la valeur plus tard, une conversion flottante sera meilleure.


    N'oublions pas que je dois également prendre en charge le formatage de XX.X, donc pour chaque valeur inférieure à 10 décimales, je devrai mettre à zéro un pad une fois, ce qui dans un float n'est possible que lors du formatage en str



    1
    votes

    Encore une autre façon de le décomposer

    (?: 0 [1-9] | [1-5] \ d) \. [05] | 60 \ .0 | 99 \ .9

    Développé

       (?: 0 [1-9] | [1-5] \d )
       \. [05] 
    |  
       60\.0
    |  
       99\.9
    


    0 commentaires