2015-07-14 3 views
5

Ich möchte Logikstrings analysieren und alle Kombinationen von Elementen, die in einer "und" Logik sind. Zum Beispiel für die Zeichenfolge '(A und (B oder C))' sollte ich [[A, B], [A, C]] und für die Zeichenfolge '(A und B und (C oder D und F) oder F und G) 'Ich sollte [[A, B, C], [A, B, D, F], [F, G]] bekommen.Get Elemente in "AND" in Logik-String mit Python

Ich versuche, Pyparsing zu verwenden. Im Anschluss an diesen Beitrag hier parsing a complex logical expression in pyparsing in a binary tree fashion schaffe ich mit den Buchstaben eine verschachtelte Liste bekommen gruppiert nach Vorlieben („und“ Präferenz hat über „oder“ und Klammer überschreibt diese):

import pyparsing as pp 

complex_expr = pp.Forward() 
vars = pp.Word(pp.alphas, pp.alphanums + "_") | pp.Regex(r"[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?").setName('proteins') 
clause = pp.Group(vars^(pp.Suppress("(") + complex_expr + pp.Suppress(")"))) 

expr = pp.operatorPrecedence(clause,[ 
          ("and", 2, pp.opAssoc.LEFT,), 
          ("or", 2, pp.opAssoc.LEFT,),]) 
#print expr 
complex_expr << expr 
parseresult=complex_expr.parseString('(A and B and (C or D and F) or F and G)') 
print parseresult 

Welche gibt:

[[[['A'], 'und', ['B'], 'und', [['C'], 'oder', [['D'], 'und' [ 'F']]]]] 'oder' [[ 'F'] 'und' [ 'G']]]]]

Wie kann ich dieses Ergebnis verarbeiten, um die gewünschte Ausgabe zu erzielen? Ich wäre dankbar für jede Hilfe. Ich habe versucht, pyparsing, aber ich bin offen für andere Module, die besser sein können.

Vielen Dank im Voraus.

Antwort

3

Python-Bibliotheken werden uns ein wenig helfen:

def analyse(expression): 
    # Find all used symbols 
    symbols = set(re.findall(r"\b[A-Z]\b", expression)) 
    # Find all combinations of symbols and values 
    mappings = (dict(zip(symbols, values)) for values in itertools.product([False, True], repeat=len(symbols))) 
    # Select combinations that make the whole expression true 
    solutions = [sorted(name for name in mapping if mapping[name]) for mapping in mappings if eval(expression, None, mapping)] 
    # Filter out redundant solutions 
    return sorted(s1 for s1 in solutions if not any(set(s1) > set(s2) for s2 in solutions)) 

Und lassen Sie uns testen:

assert analyse("(A and (B or C))") == [["A", "B"], ["A", "C"]] 
assert analyse("(A and B and (C or D and F) or F and G)") == [["A", "B", "C"], ["A", "B", "D", "F"], ["F", "G"]] 

Es gibt Kommentare

import re 
import itertools 

die die gewünschte Funktion Lassen Sie schreiben im Quellcode. Wie auch immer, die Hauptschritte sind:

  • Die Ausdrucksvariablen werden als Großbuchstaben aus einem Zeichen gefunden.
  • Jede Variable kann entweder True oder False sein. Wir finden alle Kombinationen.
  • Wir wählen nur solche Kombinationen aus, die den gesamten Ausdruck wahr machen.
  • Wir behalten nur minimale Lösungen, d. H. Diejenigen, die keine Obermengen anderer Lösungen sind.

Ich möchte Ihnen sehr für eine nette Frage danken. Die Python itertools hört nie auf, mich zu überraschen. ;-)

+0

Danke für die schnelle Antwort! Es funktioniert perfekt! – Rosa

Verwandte Themen