2011-08-17 13 views
6

Zakładając mam krotki jak:elementów krotki i filtrując je

[('text-1','xxx'), ('img-1','iii'), ('img-2','jjj'), ('text-2','xxx')] 

chcę odfiltrować listę i produkować nowe z elementów, które rozpoczynają się od „img”. Moja nowa lista będzie wyglądać następująco:

[('img-1','iii'), ('img-2','jjj')] 

Dzięki!

Odpowiedz

18

Jednym ze sposobów:

>>> l = [('text-1','xxx'), ('img-1','iii'), ('img-2','jjj'), ('text-2','xxx')] 
>>> [t for t in l if t[0].startswith('img')] 
[('img-1', 'iii'), ('img-2', 'jjj')] 

Innym sposobem:

>>> filter(lambda x: x[0].startswith('img'), l) 
[('img-1', 'iii'), ('img-2', 'jjj')] 

Pierwszy nazywa się lista ze zrozumieniem. Zobacz F.C.'s answer dla pokrewnej techniki. Podstawowa składnia to [{expression} for {item_var_or_vars} in {iterable} if {boolean_expression}]. To semantycznie równoważne coś takiego:

new_list = [] 
for {item_var_or_vars} in {iterable}: 
    if {boolean_expression}: 
     new_list.append({expression}) 

if {boolean_expression} bit nie jest obowiązkowe, podobnie jak to jest w pętli for.

Druga to po prostu wbudowana funkcja filter, która przyjmuje funkcję testową i iterowalną, i zwraca listę zawierającą każdy element, który "przekazuje" funkcję testową. lambda, jeśli jeszcze go nie widziałeś, to tylko szybki sposób na zdefiniowanie funkcji. Można to zrobić w zamian:

def keep_this_element(element): 
    return element[0].startswith('img') # returns True for ('img...', '...') 

new_list = filter(keep_this_element, l) # keeps only elements that return True 
+1

To jest świetne. Czy istnieje nazwa obu tych technik? Chciałbym więcej przeczytać o tych metodach. Dzięki. – sidewinder

+1

@Awais, zobacz moje edycje dla bardziej szczegółowego wyjaśnienia. – senderle

+1

Pierwszym z nich jest [zrozumienie list] (http://docs.python.org/tutorial/datastructures.html#list-comprehensions) drugim jest [filtr] (http://docs.python.org/library/functions .html # filter) i wyrażenie [lambda] (http://docs.python.org/reference/expressions.html#lambda) – agf

6

Może coś takiego?

l2 = [item for item in l1 if item[0].startswith('img')] 
+0

To jest dobre. Dzięki! – sidewinder

3

tylko inny sposób z generator expression (może to zrobić jakąś różnicę na dużych listach)

>>> l = [('text-1','xxx'), ('img-1','iii'), ('img-2','jjj'), ('text-2','xxx')] 
>>> (x for x in l if x[0].find('img') == 0) 
0: <generator object <genexpr> at 0x917a00> 
>>> gen = (x for x in l if x[0].find('img') == 0) 
>>> list(gen) 
1: [('img-1', 'iii'), ('img-2', 'jjj')] 
1
tuple_filter = lambda t, i, w: filter(lambda a: a[i].startswith(w), t) 
newtuple = tuple_filter(thetuple, 0, 'img')