Seite 1 von 1

Liste enthält ALLE Werte einer anderen Liste -reg. Ausdrücke

Verfasst: Mittwoch 26. Januar 2011, 17:25
von api
Hallo,

ich möchte gerne überprüfen, ob ALLE Werte einer Liste in einer anderen Liste vorhanden sind. Solange es sich um einfache Werte handelt, ist das kein Problem - bei der Überprüfung habe ich die Listen in Sets umgewandelt und führe den Test mit "issubset" durch. Das funktioniert auch soweit.
Nun kann es aber sein, dass auch reguläre Ausdrücke zur Überprüfung anstehen - also, das Prg soll schauen, ob ALLE Werte (auch reg. Ausdrücke) in der anderen Liste vorkommen. Die regulären Ausdrücke sollen natürlich angewendet werden.

Als Script sieht es zur Zeit in etwa so aus:

Code: Alles auswählen

ProjectList = [['D', '1', 'fumm0134', 'test', '/tmp/software/bin', 'PRD'], ['D', '1', 'fumm0071', 'test', '/tmp/software/bin', 'UAT']]
PatternList1 = ['fumm0134', 'PRD']
PatternList2 = ['134$', 'PRD']

NewList1 = []
for row in ProjectList:
  if set(PatternList1).issubset(set(row)):
    NewList1.append(row)

NewList2 = []
for row in ProjectList:
  if set(PatternList2).issubset(set(row)):
    NewList2.append(row)

print NewList1
print NewList2
Die Ausgabe wäre dann:
[['D', '1', 'fumm0134', 'test', '/tmp/software/bin', 'PRD']]
[]
Der 1. Fall funktioniert ja (PatternList1).
Der 2. Fall enthält als 1. Wert einen reg. Ausdruck (PatternList2).

Ziel wäre hier die gleiche Ausgabe in beiden Fällen!

Muss ich in diesem Fall verschachtelte Schleifen verwenden? Oder weiss jemand hier was besseres?

CU,
API

Re: Liste enthält ALLE Werte einer anderen Liste -reg. Ausdr

Verfasst: Mittwoch 26. Januar 2011, 18:02
von Hyperion
Sehe ich das richtig, dass Unterlisten immer komplett übernommen werden, sobald ein Kriterium aus der Pattern-Liste passt?

Wie tief verschachtelt kann es denn noch werden? Sind es immer Listen in einer Liste? Oder kann es da noch tiefer / höher gehen? Also Listen in Listen, Elemente auf oberster Ebene? Und wenn ja, wie wird dann die Übernahme geregelt?

Wenn Du auf RegExps testen willst, kannst Du den Weg über sets natürlich vergessen. Du musst eben für jedes Element der pattern-Liste alle Elemente der jeweiligen Prüfliste durchgehen und gucken, ob der re matcht. Sobald der erste gematcht hat, kannst Du den ja abbrechen und mit dem nächsten Ausdruck weiter machen.

Edit: So könnte ich es mir vorstellen. Das ganze musst Du dann eben noch entsprechend auswerten und die passenden Zeilen in Deine Ergebnisliste packen:

Code: Alles auswählen

In [81]: patterns = [r".*134$", r"PRD"]

In [82]: projects = [['D', '1', 'fumm0134', 'test', '/tmp/software/bin', 'PRD'],
 ['D', '1', 'fumm0071', 'test', '/tmp/software/bin', 'UAT']]

In [83]: [all(any(imap(partial(re.match, pattern), row)) for pattern in patterns) for row in projects]
Out[83]: [True, False]
Könnte man mit itertools.compress realisieren. Wohl gemerkt gehe ich davon aus, dass es sich immer um Listen in einer Oberliste handelt.

Ach so, partial stammt aus dem functool-, imap aus dem itertools-Modul.

Re: Liste enthält ALLE Werte einer anderen Liste -reg. Ausdr

Verfasst: Mittwoch 26. Januar 2011, 18:11
von api
@Hyperion:
Sehe ich das richtig, dass Unterlisten immer komplett übernommen werden, sobald ein Kriterium aus der Pattern-Liste passt?
Es müssen immer ALLE Kriterien einer Pattern-Liste passen.
Wie tief verschachtelt kann es denn noch werden? Sind es immer Listen in einer Liste? Oder kann es da noch tiefer / höher gehen? Also Listen in Listen, Elemente auf oberster Ebene? Und wenn ja, wie wird dann die Übernahme geregelt?
So wie die Liste im Beispiel angegeben ist - tiefer geht es nicht. Also 2 Dimensionen.
Wenn Du auf RegExps testen willst, kannst Du den Weg über sets natürlich vergessen. Du musst eben für jedes Element der pattern-Liste alle Elemente der jeweiligen Prüfliste durchgehen und gucken, ob der re matcht. Sobald der erste gematcht hat, kannst Du den ja abbrechen und mit dem nächsten Ausdruck weiter machen.
Wenn du damit die PatternList meist, ja - ich könnte nach dem 1. Treffer mit dem nächsten Ausdruck weitermachen...
Das läuft dann also doch auf verschachtelte Schleifen hin, oder?

Re: Liste enthält ALLE Werte einer anderen Liste -reg. Ausdr

Verfasst: Mittwoch 26. Januar 2011, 18:14
von Hyperion
Hier mit Rausfiltern der passenden Projektlisten:

Code: Alles auswählen

In [99]: list(compress(projects, (all(any(imap(partial(re.match, pattern), row)) for pattern in patterns) for row in projects)))
Out[99]: [['D', '1', 'fumm0134', 'test', '/tmp/software/bin', 'PRD']]

Re: Liste enthält ALLE Werte einer anderen Liste -reg. Ausdr

Verfasst: Mittwoch 26. Januar 2011, 18:27
von api
Erstmal Danke für die schnelle Antwort.

Allerdings verstehe ich den Code nicht wirklich... :?

Ich werd das wohl mal nachschlagen müssen - kannst du mir aber mal nen Hinweis darauf geben, wo ich das Kommando "imap" finde?

Re: Liste enthält ALLE Werte einer anderen Liste -reg. Ausdr

Verfasst: Mittwoch 26. Januar 2011, 18:35
von api
@Hyperion:

Ich habe 2 Python-Versionen zur Auswahl: 2.4.6 oder 3.1.2

In 3.1.2 meckert er immer das imap an - inzwischen weiss ich, dass es zu itertools gehört...

Re: Liste enthält ALLE Werte einer anderen Liste -reg. Ausdr

Verfasst: Mittwoch 26. Januar 2011, 18:49
von Hyperion
api hat geschrieben: In 3.1.2 meckert er immer das imap an - inzwischen weiss ich, dass es zu itertools gehört...
In Python >= 3.x gibt es kein imap mehr, da das late"map" aus den Standard-Funktionen aus 2.x nun einen Iterator liefert und keine Liste mehr. Sprich, das alte imap ist das neue map. imap gibts nicht mehr in 3.x

Der Code sieht komplizierter aus, als er ist. Man muss sich da nur ein wenig reindenken und von "innen nach außen" lesen.

Im inneren führe ich ein re.match mit einem pattern durch das (i)map gegen alle Elemente einer Reihe aus. Das partial ist notwendig, da re.match zwei Parameter verlangt, man bei map aber nur einen übergeben darf. Matcht der Ausdruck mindestens einmal, so liefert das any() ein True. Nun muss das für alle pattern einer pattern-Liste ja gelten, weswegen das all zum Tragen kommt in einem Generatorausdruck, in dem ich über die pattern iteriere. Da drum herum gehe ich einfach wieder per Generatorausdruck über alle rows aus der Projektliste. Ganz drum herum nutze ich compress, welches nur die Elemente eines Iterable zurückliefert, bei denen ein korrespondierendes Objekt True ist.

Re: Liste enthält ALLE Werte einer anderen Liste -reg. Ausdr

Verfasst: Mittwoch 26. Januar 2011, 18:55
von api
@Hyperion:

Ich habe jetzt folgendes versucht:

Code: Alles auswählen

for row in ProjectList:
  NewList2 = list(compress(ProjectList, (all(any(map(partial(re.match, pattern), row)) for pattern in PatternList4) for row in ProjectList)))

print (NewList2)
Und was soll ich sagen, es funzt !!! Verwendet habe ich nun Python 3.1.2 - weil das compress erst ab 2.7 verfügbar ist...

Ich danke dir :D (Wenn ich mir den Code auch nochmal näher ansehen muss... :wink: )