1
votes

Comment analyser tous les coefficients d'une chaîne polynomiale en python

J'ai un fichier .txt qui contient d'énormes polynômes stockés sous forme de chaînes. Un exemple représentatif serait le suivant. 6 * n101110111 * n111111111 + 3 * n101111101 + 6 * n101111111 + n111111111 Mais en général, les polynômes sont constitués de «n + str (tous les chiffres binaires possibles de longueur 9)» multipliés dans des ordres différents avec des coefficients. Le nombre de termes et «+» n'est pas connu à l'avance. Le résultat devrait être,

{ n101110111*n111111111: 6, n101111101: 3, n101111111: 6, n111111111 :1}

Encore mieux serait de l'obtenir sous forme de dictionnaire

[6,3,6,1]


1 commentaires

La chaîne que vous affichez constitue-t-elle une ligne typique dans le fichier? Si tel est le cas, est-ce que chaque ligne du fichier est intéressante et la partie 6 * n101110111 * n111111111 est-elle toujours au début d'une ligne? Cet exemple comporte quatre termes séparés par des signes plus. Toutes les chaînes d'intérêt ont-elles exactement quatre termes? Sinon, quel est le nombre maximum de termes? Certains des signes plus peuvent-ils être des signes moins? Veuillez fournir ces informations en modifiant votre question plutôt qu'en le faisant dans un commentaire.


4 Réponses :


3
votes

Une expression régulière comme celle-ci ((\ d)? \ *? ((?: n \ d +) (?: \ * n \ d +) *)) ( Regex demo ) fera le travail

line = "6*n101110111*n111111111 + 3*n101111101 + 6*n101111111 + n111111111"
res = {}

matches = re.findall(r"(?:(\d)?\*?((?:n\d+)(?:\*n\d+)*))", line)
print(matches)  # [('6', 'n101110111*n111111111'), ('3', 'n101111101'), ('6', 'n101111111'), ('', 'n111111111')]

for match in matches:
    res[match[1]] = match[0] or 1
print(res)  # {'n101110111*n111111111': '6', 'n101111101': '3', 
               'n101111111': '6', 'n111111111': 1}


0 commentaires

3
votes

Je pense avoir une solution pour vous:

stringList = yourStringHere.split("+")
outputDict = {}

for sub in stringList:
    values = sub.split("*")
    try:
        baseNum = int(values[0])
        poly = "*".join(values[1:]).strip()
    except:
        baseNum = 1
        poly = "*".join(values).strip()
    outputDict[poly] = baseNum 

Le seul inconvénient de cette approche sera que le dictionnaire contient des clés uniques et donc si vous avez d'autres pouvoirs similaires dans votre dictionnaire, ils le feront être écrasé.

Faites-moi savoir si cette approche a aidé! Meilleur!


4 commentaires

J'aime la propreté de la solution, mais 'n111111111: 1' ne sera pas analysé par votre solution


Oui, vous avez raison, je n'ai pas remarqué que le dernier élément n'avait pas le numéro de base. Laissez-moi changer cela pour vous.


Hé! Merci beaucoup pour votre solution. Cela fonctionne et comme il est plus difficile pour moi de comprendre une solution basée sur les regex, j'accepte votre réponse.


Merci beaucoup! Je suis heureux que cela ait aidé. Bonne chance pour votre projet! Je vous encourage également à vous renseigner sur les regex, c'est un outil très puissant.



3
votes

vous pouvez utiliser:

{'n101110111*n111111111': 6,
 'n101111101': 3,
 'n101111111': 6,
 'n111111111': 1}

sortie:

import re

s = '6*n101110111*n111111111 + 3*n101111101 + 6*n101111111 + n111111111'

l = [g.group().split('*', 1)  for g in re.finditer(r'\b([\dn*]+)\b', s)]
{e[-1]: 1 if len(e) == 1 else int(e[0]) for e in l}


1 commentaires

Vous pouvez raccourcir votre classe de caractères à [* n \ d] . Bon python, cependant. ^^



1
votes

Vous pouvez utiliser l'expression régulière

(?:        # begin a non-capture group
  (\d+)    # match 1+ digits in capture group 1
  \*       # match '*'
)          # end non-capture group
?          # optionally match non-capture group
([^ +-]+)  # match 1+ chars other than spaces, '+', and '-' in
           # capture group 2

Démo Python

Le moteur d'expression régulière effectue les opérations suivantes pour chaque correspondance:

r" (?:(\d+)\*)?([^ +-]+)


1 commentaires

Je ne suis pas familier avec Python, mais créer un hachage à partir du contenu des groupes de capture devrait être simple, comparable au code Ruby str.gsub (r) .with_object ({}) {| _, h | h [$ 2] = ($ 1 || 1) .to_i} # => {"n101110111 * n111111111" => 6, "n101111101" => 3, "n101111111" => 6, "n111111111" => 1} , où r est l'expression régulière.