Hallo,
ich möchte mehrere längere Zeichenketten der Form
"+3.0AAACD + 5.0ACFDB - 10.0EAADF", usw.
automatisch in mathematische Funktionen von mehreren Variablen verwandeln. (Dabei wird AAA als A^3 interpretiert.)
Im obigen Fall wäre es
f(A,B,C,D,E,F) = +3.0AAACD + 5.0ACFDB - 10.0EADF
so dass man z.B.
f(2,1,1,1,1,1) = +24 + 10 - 20 = 14 bekommt. Für meine Zwecke brauche ich nur ganze Zahlen in die Funktion einzusetzen.
Ich habe zwar ein paar Ideen, wie man dies sehr umständlich machen könnte, bin aber überzeugt, dass es ganz leicht gehen müßte.
Vielen Dank im voraus!
Aus einer Zeichenkette eine Funktion machen
Spontan fällt mir eine quick'n dirty Lösung ein, aber die werde ich lieber nicht zeigen (das gibt immer Prügel hier im Forum).
Für eine saubere Lösung wäre wichtig zu wissen was genau es heißt, wenn du schreibst "der Form". Diese "Form" müsstest du etwas allgemeiner spezifizieren, d.h. der Aufbau müsste klar definiert werden (Welche Variablen können vorkommen? Sind es immer fünf hintereinander? Steht am Anfang IMMER ein Fließkommawert mit genau einer Stelle nach dem Dezimalpunkt? Etc.)
Für eine saubere Lösung wäre wichtig zu wissen was genau es heißt, wenn du schreibst "der Form". Diese "Form" müsstest du etwas allgemeiner spezifizieren, d.h. der Aufbau müsste klar definiert werden (Welche Variablen können vorkommen? Sind es immer fünf hintereinander? Steht am Anfang IMMER ein Fließkommawert mit genau einer Stelle nach dem Dezimalpunkt? Etc.)
Danke für die schnelle Antwort!
Die Zeichenketten bestehen aus höchstens 16 Buchstaben von A,B,C,...P.
Jede Zeichenkette fängt so "+a.0ABCFD + ... + " oder "-a.0ABCFD + ... + " mit einer Ganzzahl "a".
Schlimmstenfalls könnte sowas als Zeichenkette vorkommen:
+12.0AHIAD -10.0AEEKK +16.0LJIDG +10.0DFFDA -6.0ANNFF -4.0CBBOJ -4.0LCCBG +4.0NLLHF -10.0AHHEE -10.0KDDAK +4.0ICIOJ +10.0ECCEA +10.0BEEBA +10.0AAADD +20.0HKKNF +5.0JJJJA +2.0BAABA -40.0KDGAF -10.0AJJFF -8.0MLINA -10.0FIIAF -16.0CFIEJ +10.0AHHKK +4.0NCNNG +4.0ICING -16.0BMFGD -16.0JKOLE -2.0HCCHA +10.0LLJJA -4.0BEELG -12.0BAALG +10.0DBBAD -4.0HMMID -4.0ILIOF -8.0JFCLA -30.0DGAGD +4.0BMBNE +4.0CHHIK -4.0BMBOD +2.0NOONA
Die Zeichenketten bestehen aus höchstens 16 Buchstaben von A,B,C,...P.
Jede Zeichenkette fängt so "+a.0ABCFD + ... + " oder "-a.0ABCFD + ... + " mit einer Ganzzahl "a".
Schlimmstenfalls könnte sowas als Zeichenkette vorkommen:
+12.0AHIAD -10.0AEEKK +16.0LJIDG +10.0DFFDA -6.0ANNFF -4.0CBBOJ -4.0LCCBG +4.0NLLHF -10.0AHHEE -10.0KDDAK +4.0ICIOJ +10.0ECCEA +10.0BEEBA +10.0AAADD +20.0HKKNF +5.0JJJJA +2.0BAABA -40.0KDGAF -10.0AJJFF -8.0MLINA -10.0FIIAF -16.0CFIEJ +10.0AHHKK +4.0NCNNG +4.0ICING -16.0BMFGD -16.0JKOLE -2.0HCCHA +10.0LLJJA -4.0BEELG -12.0BAALG +10.0DBBAD -4.0HMMID -4.0ILIOF -8.0JFCLA -30.0DGAGD +4.0BMBNE +4.0CHHIK -4.0BMBOD +2.0NOONA
Ich würde es erstmal via Regex zerlegen:
Zweiter Schritt wäre dann ein Dictionary für die Variablen anzulegen. Dann aus dem Dict ein Dict mit Lambdas erzeugen. Zuletzt schrittweise die Tupel abarbeiten.
Code: Alles auswählen
>>> text = "+3.0AAACD + 5.0ACFDB - 10.0EAADF"
>>> import re
>>> re.findall(r"\s*([+-]{1})\s*(\d+\.?\d?)(\w+)", text)
[('+', '3.0', 'AAACD'), ('+', '5.0', 'ACFDB'), ('-', '10.0', 'EAADF')]
Achtung: User ist ein Python-Lehrling!
Mal ein quick'n'dirty Ansatz:
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf-8
import operator
import re
from functools import partial
PART_RE = r'\s*([+-])\s*([0-9]+)\.0([A-P]+)'
product = partial(reduce, operator.mul)
class Function(object):
def __init__(self, parts):
self.parts = parts
def __call__(self, *args):
return sum(c * product(args[v] for v in vs) for c, vs in self.parts)
@classmethod
def from_string(cls, string):
def build_part((sign, constant, variables)):
return (int(sign + constant),
[ord(c) - ord('A') for c in variables])
return cls(map(build_part, re.findall(PART_RE, string)))
def main():
data = '+3.0AAACD + 5.0ACFDB - 10.0EADF'
func = Function.from_string(data)
print func(2, 1, 1, 1, 1, 1)
if __name__ == '__main__':
main()
Und 'ne Variante ohne RE:
Edit: Zeile 2 nachträglich geändert: replace() und lstrip() vertauscht.
Code: Alles auswählen
def evaluate(expr, values):
expressions = expr.replace('-','+-').lstrip('+').split('+') # geändert!
total = 0
for e in expressions:
a, b = e.strip().split('.')
val = int(a)
for v in b[1:]:
val *= values[v]
total += val
return total
expr = """+12.0AHIAD -10.0AEEKK +16.0LJIDG +10.0DFFDA -6.0ANNFF -4.0CBBOJ
-4.0LCCBG +4.0NLLHF -10.0AHHEE -10.0KDDAK +4.0ICIOJ +10.0ECCEA +10.0BEEBA
+10.0AAADD +20.0HKKNF +5.0JJJJA +2.0BAABA -40.0KDGAF -10.0AJJFF -8.0MLINA
-10.0FIIAF -16.0CFIEJ +10.0AHHKK +4.0NCNNG +4.0ICING -16.0BMFGD -16.0JKOLE
-2.0HCCHA +10.0LLJJA -4.0BEELG -12.0BAALG +10.0DBBAD -4.0HMMID -4.0ILIOF
-8.0JFCLA -30.0DGAGD +4.0BMBNE +4.0CHHIK -4.0BMBOD +2.0NOONA"""
values = dict(zip('ABCDEFGHIJKLMNOP',[1,2,-2,0,1,3,-2,2,3,4,-4,0,1,1,-1,3]))
print evaluate(expr, values)
Zuletzt geändert von numerix am Montag 21. Dezember 2009, 19:17, insgesamt 1-mal geändert.
Nochmal etwas ausführlicher und etwas abweichend von meinem ursprünglischen Plan:
Code: Alles auswählen
#!/usr/bin/env python
import re
text = "+3.0AAACD + 5.0ACFDB - 10.0EAADF"
class expression:
def __init__(self, t):
self.op, self.val, self.items = t
def evaluate(self, lut):
lut['+'] = 1
lut['-'] = -1
accu = 1
accu *= lut[self.op]
accu *= int(float(self.val))
for i in self.items:
accu *= lut[i]
return accu
params = { 'A': 2, 'B': 1, 'C': 1, 'D': 1, 'E': 1, 'F': 1 }
print(
sum(
[expression(e).evaluate(params) for e in re.findall(
r"\s*([+-]{1})\s*(\d+\.?\d?)(\w+)", text
)]
)
)
Achtung: User ist ein Python-Lehrling!
Sorry, war eine Missachtung von PEP8 - ist für "mehrsprachige" manchmal schwierig an übliche Konventionen zu denken. Die [] sind für die List-Comprehension?!derdon hat geschrieben:Wozu die eckigen Klammern? Warum schreibst du `expression` klein?
Achtung: User ist ein Python-Lehrling!
Code: Alles auswählen
>>> sum([i for i in xrange(4,44,4)])
220
>>> sum((i for i in xrange(4,44,4)))
220
>>> sum(i for i in xrange(4,44,4))
220
Hier noch eine Alternative mit ast:
http://www.python-forum.de/post-149756.html#149756
http://www.python-forum.de/post-149756.html#149756