2011-10-01 17 views
7

Mam listę i chcę użyć pewnej funkcji tylko na tych wpisach, które spełniają pewien warunek - pozostawiając pozostałe wpisy niezmodyfikowane.Zrozumienie listy Pythona - proste

Przykład: Załóżmy, że pomnożę przez 2 tylko te elementy, które są parzyste.

a_list = [1, 2, 3, 4, 5] 

kupna wynik:

a_list => [1, 4, 3, 8, 5] 

Ale [elem * 2 for elem in a_list if elem %2 == 0] plony [4, 8] (działał jako filtr dodatkowo).

Jaki jest prawidłowy sposób na rozwiązanie tego problemu?

Odpowiedz

18

Użyj conditional expression:

[x * 2 if x % 2 == 0 else x 
for x in a_list] 

(uwaga Math Geek jest: można również rozwiązać ten konkretny przypadek z

[x * (2 - x % 2) for x in a_list] 

ale wolałbym pierwszą opcję i tak;)

+0

Dzięki, działało świetnie. Ponadto, dzięki za zmiany, spróbuję użyć tego samego formatu. –

2
a_list = [1, 2, 3, 4, 5] 

print [elem*2 if elem%2==0 else elem for elem in a_list ] 

lub, jeśli masz bardzo długą listę, którą chcesz zmodyfikować w miejscu:

a_list = [1, 2, 3, 4, 5] 

for i,elem in enumerate(a_list): 
    if elem%2==0: 
     a_list[i] = elem*2 

tak, tylko nawet elementy są modyfikowane

+0

Czy lista 'a_list [:] = list_comprehension' nie działa również na wymianę na miejscu? I to bez konieczności pętli w python? – Voo

+0

@agf Więc utworzy nową listę gdzie indziej, a następnie zaktualizuje elementy? Szkoda, pomyślałem, ze względu na ograniczenia w zrozumieniu listy, możemy zagwarantować, że element będzie mógł być przywoływany tylko przed jego nadpisaniem, aby można go było zoptymalizować. – Voo

+0

@Voo Przypisanie w miejscu działa z dowolnej iteracji, więc można to zrobić z wyrażenia generatora. Po prostu to wypróbowałem i to faktycznie działa, nawet jeśli używasz 'odwróconej (a_list)' lub generatora, który daje mniej elementów niż długość listy. Nie coś, o czym myślałem wcześniej; dzięki za poruszenie pomysłu :). – agf

0

Można użyć lambda:

>>> a_list = [1, 2, 3, 4, 5] 
>>> f = lambda x: x%2 and x or x*2 
>>> a_list = [f(i) for i in a_list] 
>>> a_list 
[1, 4, 3, 8, 5] 

Edit - Myślenie o uwaga agf „s Zrobiłem 2nd wersję mojego kodu:

>>> a_list = [1, 2, 3, 4, 5] 
>>> f = lambda x: x if x%2 else x*2 
>>> a_list = [f(i) for i in a_list] 
>>> a_list 
[1, 4, 3, 8, 5] 
+0

Nie używaj "warunek i true_value lub false_value" do emulowania operacji trójskładnikowej; w Pythonie jest prawdziwa wersja. Ponadto, nie ma potrzeby, aby zawijać go w lambda w obu kierunkach, ponieważ jest to wyrażenie, a nie instrukcja, która działa poprawnie w zrozumieniu listy. 'lambda ma takie samo ograniczenie, więc zawsze jest potrzeba dla kogoś w zrozumieniu listy lub wyrażeniu generatora. – agf

+0

@agf - Rozumiem (i zgadzam się z) twój komentarz na temat lambda, ale w tym przypadku wydaje mi się to w inny sposób (choć z dala od absolutnie doskonałego) do umieszczenia na różnych poziomach logiki wyboru elementów ze zrozumienia listy . I dziękuję za resztę dotyczącą potrójnego operatora Python. Zrobiłem drugą wersję, aby to odzwierciedlić. –

+0

'lambda x:' i 'f()' ma 12 znaków, '[dla i in a_list]' ma 18 - dzięki czemu czynisz je wyraźniejszym i szybszym dzięki temu, że mają wyrażenie bardziej wbudowane niż "lambda" dla tylko sześć więcej znaków, jeśli masz zupełnie oddzielną listę, zamiast tylko nowej funkcji. – agf