2014-04-29 11 views
7

Wie kann ich eine Liste basierend auf einer anderen Liste filtern, die Teilwerte und Platzhalter enthält? Das folgende Beispiel ist das, was ich bisher:Wie filtern Sie die Liste anhand einer anderen Liste mit Platzhaltern?

l1 = ['test1', 'test2', 'test3', 'test4', 'test5'] 
l2 = set(['*t1*', '*t4*']) 

filtered = [x for x in l1 if x not in l2] 
print filtered 

Dieses Beispiel ergibt:

['test1', 'test2', 'test3', 'test4', 'test5'] 

Aber ich bin auf der Suche, die Ergebnisse basierend auf l2 auf folgende Situationen zu beschränken:

['test2', 'test3', 'test5'] 

Antwort

10

Verwenden Sie das Modul fnmatch und ein Listenverständnis mit any():

>>> from fnmatch import fnmatch 
>>> l1 = ['test1', 'test2', 'test3', 'test4', 'test5'] 
>>> l2 = set(['*t1*', '*t4*']) 
>>> [x for x in l1 if not any(fnmatch(x, p) for p in l2)] 
['test2', 'test3', 'test5'] 
+0

Gute Eins! Ich kannte einen Ansatz, der eine 'list'-Unterklasse verwendete, die reguläre Ausdrücke akzeptierte. Wusste das nicht. –

1

Sie können auch Filter() statt der Liste Verständnis, was den Vorteil haben, dass Sie leicht Ihre Filterfunktion für mehr Flexibilität tauschen:

>>> l1 = ['test1', 'test2', 'test3', 'test4', 'test5'] 
>>> l2 = set(['*t1*', '*t4*']) 
>>> filterfunc = lambda item: not any(fnmatch(item, pattern) for pattern in l2) 
>>> filter(filterfunc, l1) 
Out: ['test2', 'test3', 'test5'] 
>>> # now we don't like our filter function no more, we assume that our l2 set should match on any partial match so we can get rid of the star signs: 
>>> l2 = set(['t1', 't4']) 
>>> filterfunc = lambda item: not any(pattern in item for pattern in l2) 
>>> filter(filterfunc, l1) 
Out: ['test2', 'test3', 'test5'] 

Auf diese Weise können Sie sogar verallgemeinern Ihre filterfunc mit mehreren Mustern arbeiten setzt:

>>> from functools import partial 
>>> def filterfunc(item, patterns): 
    return not any(pattern in item for pattern in patterns) 
>>> filter(partial(filterfunc, patterns=l2), l1) 
Out: ['test2', 'test3', 'test5'] 
>>> filter(partial(filterfunc, patterns={'t1','test5'}), l1) 
Out: ['test2', 'test3', 'test4'] 

Und natürlich könnte man leicht aktualisieren Sie Ihre filterfunc reguläre Ausdrücke in dem Mustersatz zu akzeptieren, zum Beispiel.

1

Ich denke, die einfachste Lösung für Ihren Anwendungsfall ist für die Teilzeichen einfach zu testen mit Python in (obwohl dies bedeutet, dass Ihre Sternchen zu entfernen):

def remove_if_not_substring(l1, l2): 
    return [i for i in l1 if not any(j in i for j in l2)] 

so dass unsere Daten hier:

l1 = ['test1', 'test2', 'test3', 'test4', 'test5'] 
l2 = set(['t1', 't4']) 

Und unsere Funktion mit ihrem Aufruf:

remove_if_not_substring(l1, l2) 

returns:

['test2', 'test3', 'test5']